Wird super() gebrochen in Python-2.x?
Es ist oft gesagt, dass super
sollte vermieden in Python 2. Ich gefunden habe in meiner Verwendung von super
in Python 2 dass es nie wieder so handelt, wie ich erwarte, wenn ich alle Argumente-wie das Beispiel:
super(ThisClass, self).some_func(*args, **kwargs)
Scheint es mir, diese Niederlagen der Zweck der Verwendung super()
, es ist weder kürzer, oder viel besser als TheBaseClass.some_func(self, *args, **kwargs)
. Für die meisten Zwecke method resolution order ist ein fernes Märchen.
- Andere als die Tatsache, dass 2.7 ist das Letzte major release zu Python 2, warum funktioniert super bleiben, gebrochen in Python 2?
- Wie und warum hat Python 3 ist super geändert? Gibt es irgendwelche Vorbehalte?
- Wann und warum sollte ich
super
vorwärts gehen?
- Sie nicht geben Sie irgendein Beispiel, warum Sie denken, dass Sie super ist gebrochen, außer, dass es nicht kürzer als der Aufruf der Basisklasse explizit die weder hier noch dort... Sie offensichtlich nicht verstehen, was " super() ist ein (up-Aufruf sicher mit Mehrfachvererbung).
- Das wäre subjektiv und unscharf ist nicht Teil meines namens 🙂
- Gut, Nein. "Broken" ist nicht ein subjektiver Begriff und super ist notwendig, in einigen Fällen. So brauchen Sie sich nicht zu erklären, warum Sie denken, dass Sie super ist gebrochen (anders als durch Verweis zu einem Artikel, nicht sagen, dass) und Sie zeigen keine Erscheinung, zu verstehen, was super ist (Tipp: es ist nicht das äquivalent der alternative, die Sie zeigen).
- Wenn Sie sagen, dass
TheBaseClass.some_func(self, *args, **kwargs)
ist besser alssuper
Sie sind unter der Annahme, dassTheBaseClass
ist immer der Vorfahr vonThisClass
die möglicherweise nicht der Fall sein, wenn Sie mehrfache Vererbung (oder jemand fügt es danach). Es könnte sein, dasssuper(ThisClass, self)
löst etwas anderes alsTheBaseClass
.super()
. Die Frage ist also: wollen Sie zum aufrufen der "next guy" in der Kette (wahrscheinlich) oder Ihr anrufen möchtenTheBaseClass
genau.
Du musst angemeldet sein, um einen Kommentar abzugeben.
super()
ist nicht kaputt-es sollte nur nicht als standard-Weg für den Aufruf einer Methode der Basisklasse. Dies änderte sich nicht mit Python 3.x. Das einzige, was sich verändert hat, ist, dass Sie nicht brauchen, um passieren die Argumenteself, cls
im standard-Fall, dassself
ist der erste parameter der aktuellen Funktion undcls
ist die Klasse aktuell definiert.Bezüglich Ihrer Frage, wenn Sie auch tatsächlich zu nutzen
super()
meine Antwort wäre: kaum jemals. Ich persönlich versuchen zu vermeiden, die Art der Mehrfachvererbung machen würdesuper()
nützlich.Bearbeiten: Ein Beispiel aus dem realen Leben, die ich einmal lief: ich hatte einige Klassen definieren
run()
Methode hatte, von denen einige Basis-Klassen. Ich verwendetsuper()
Aufruf der geerbten Konstruktoren -- ich wusste nicht, dass es darauf ankam, denn ich war mit einfachvererbung nur:Stell dir vor, es gab mehrere Klassen, die alle mit eigener Konstruktor Prototypen, und alle mit derselben Schnittstelle
run()
.Nun wollte ich hinzufügen, dass einige zusätzliche Funktionen, um alle diese Klassen, sagen die Protokollierung. Die zusätzliche Funktionalität benötigt, eine zusätzliche Methode definiert werden, auf alle diese Klassen, sagen
info()
. Ich wollte nicht in die ursprünglichen Klassen, sondern definieren, einen zweiten Satz von Klassen Erben von der ursprünglichen, hinzufügen derinfo()
- Methode und erbt von einem mix-in die Bereitstellung der eigentlichen Anmeldung. Nun, ich konnte nicht verwendensuper()
im Konstruktor nicht mehr, so habe ich direkte Aufrufe:Hier Dinge, die aufhören zu arbeiten. Die
super()
nennen, die in der Basisklasse Konstruktor plötzlich ruftLogger.__init__()
, undBLogged
kann nichts über es nicht tun. Es gibt tatsächlich keinen Weg, um diese Arbeit zu machen, außer für das entfernen dersuper()
Anruf inB
selbst.[Noch ein Edit: ich scheine nicht zu haben, aus meiner Sicht, wie aus all den Kommentaren hier und unter den anderen Antworten. Hier ist, wie dieser code funktioniert mit
super()
:Vergleichen Sie diese mit der Verwendung von expliziten Superklasse aufruft. Sie entscheiden, welche version Sie bevorzugen.]
Diese und ähnliche Geschichten sind es, warum ich denke, dass
super()
sollte nicht als der normale Weg, der Aufruf von Methoden der Basisklasse. Es bedeutet nichtsuper()
ist gebrochen.super(B, self)
, und diese solltendef
sclass
es?self._logger = Logger("B")
- mischen von beliebigen Klassen in einem Baum hat nie gearbeitet. Sie können denken, der einen ähnlich kaputten Beispiel, aber mit direkten aufrufen. Die Klassen entworfen werden müssen, zusammen zu arbeiten. Undsuper
helfen können, wenn Sie es nicht sind. Aber, wie der Artikel sagt, du bist besser dran mit übergeben der Argumente als Stichwörter beim aufrufen der Superklasse. Dann ist dein problem würde nicht existieren, wenn dieLogger
Klasse korrekt verwendetsuper
.super()
. Ich denke nicht, dass es gebrochen zu alle. Ich würde gerne callb.run_logged(value)
auf eineBLogged
Instanzb
, nichtb._logger.run_logged(value)
.super()
ist nicht gebrochen, in Python 2 oder Python 3.Betrachten wir die Argumente aus dem blog post:
OK, Sie können Zustimmen oder nicht, dass, es ist ziemlich subjektiv. Was soll es denn dann als?
super()
ist ein Ersatz für den Aufruf von der Oberklasse direkt, so scheint der name in Ordnung für mich. Es ruft NICHT die Oberklasse direkt, denn wenn das war alles, was Sie Tat, es wäre sinnlos, als könnte man Sie trotzdem. OK, zugegeben, das mag nicht offensichtlich sein, aber die Fälle, wo Sie brauchensuper()
sind in der Regel nicht offensichtlich. Wenn Sie es brauchen, tun Sie einige ziemlich haarige Mehrfachvererbung. Es ist nicht zu offensichtlich sein. (Oder du machst ein einfaches mixin, in dem Fall ist es ziemlich offensichtlich, und verhält sich wie erwartet, auch wenn Sie nicht die Dokumentation Lesen).Wenn Sie anrufen können die Oberklasse direkt, das ist wahrscheinlich das, was Sie am Ende tut. Das ist die einfache und intuitive Art und Weise, es zu tun.
super()
kommt nur ins Spiel, wenn das nicht funktioniert.Ja, weil es entworfen ist, um ein problem zu lösen mit zu tun. Sie können rufen Sie die Oberklasse direkt, wenn, und nur wenn Sie genau wissen, welche Klasse das ist. Die Sie nicht für Mixins in Verbindung, zum Beispiel, wenn die Klasse Hierarchie ist so versaut, dass Sie tatsächlich vereinigen sich die beiden äste (was ist das typische Beispiel in allen Beispielen der Verwendung
super()
).So lange, wie jede Klasse in Ihrer Klassenhierarchie hat einen gut definierten Platz, den Aufruf der Superklasse direkt funktioniert. Wenn nicht, dann funktioniert es nicht, und in diesem Fall müssen Sie
super()
statt. Das ist der Punkt, dersuper()
dass es zahlen, was die "nächste Superklasse" ist nach der MRO, ohne Sie ausdrücklich angeben, denn man kann nicht immer tun, weil Sie nicht immer wissen, was es ist, zum Beispiel bei der Verwendung von Mixins in Verbindung.Eh. OK?
super()
nicht an Ihre Superklasse.Yeah, Sie sagte,.
super()
und direkt aufrufen.Yeah, Sie sagte das auch.
Also, es gibt zwei Argumente dagegen: 1. Der name ist schlecht. 2. Verwenden Sie es konsequent.
Nicht übersetzen, es wird "gebrochen" oder die, die es werden sollten "vermieden".
Du scheinst zu unterstellen in Ihrem Beitrag, dass
ist nicht eine unendliche Rekursion. Es ist, und super wäre richtiger.
Auch, ja, Sie sind erforderlich, um alle übergeben Argumente zu
super()
. Das ist ein bisschen wie beschweren sich, dassmax()
funktioniert nicht wie erwartet, es sei denn, Sie übergeben Sie alle zahlen, die Sie überprüfen möchten.In 3.x, jedoch weniger Argumente sind nötig: Sie können dies
super().foo(*args, **kwargs)
stattsuper(ThisClass, self).foo(*args, **kwargs)
.Ich bin jedenfalls nicht sicher auf alle Situationen beim super sollte vermieden werden. Sein Verhalten ist nur "komisch", wenn MI beteiligt ist, und bei der MI beteiligt ist,
super()
ist im Grunde Ihre hoffe nur, dass für eine richtige Lösung. In Einzel-Vererbung es ist nur etwas wordier alsSuperClass.foo(self, *args, **kwargs)
, und macht nichts anders.Ich glaube, ich Stimme mit Sven, dass diese Art von MI ist es Wert zu vermeiden, aber ich bin nicht einverstanden, dass
super
ist es Wert zu vermeiden. Wenn Ihre Klasse soll vererbt werden,super
bietet den Benutzern Ihrer Klasse Hoffnung MI zu arbeiten, wenn Sie sind seltsam in dieser Weise, so macht es Ihre Klasse mehr nutzbar.super()
ist die "einzige Hoffnung", wenn mehrfache Vererbung beteiligt ist. Es gibt clas hierachies, die erfordern, dasssuper()
, aber vielen Klassen-Hierarchien mit Mehrfachvererbung nicht.super
nicht geben Ihnen etwas. Auf der anderen Seite, werden Sie nicht verlieren alles, was durch die Verwendungsuper
entweder. Also, ich würdesuper
.super()
. Ich benutzte es eine Menge, und es brach eine Menge von meinem code. Mittlerweile, jedes mal wenn ich Begegnungsuper()
in meinem code habe ich es rauseditieren.super
, dass Sie behalten durch die Verwendung vonSuperClass.method(...)
? Ich Sprach die Probleme in der Frage genannten, nicht den Artikel, denn eigentlich hatte er Fragen.__init__()
möchte ich nennen, und ich will nichtsuper()
Sie eine andere sein, je nach Kontext. Und ich do verwenden Sie Mehrfachvererbung.super()
in Fällen, in denen Sie nicht genau wissen, welche Methode Sie aufrufen müssen. 🙂 Wenn du hast, dann könntest du einfach rufen.super()
sollte nicht als die standard-Art des Aufrufs Basis-Klasse Methoden. Viele Menschen tun das, und Devin auch vorschlagen, dies zu tun.super()
oder explizite Aufrufe. Später, als ich eingeführt mix-ins weiter unten in der Hierarchie, die altensuper()
fordert mich etwas.super()
funktioniert. Ich weiß, warum mein Beispiel brach und wie man es beheben, sowohl mitsuper()
und explizite Superklasse aufruft. Die version mitsuper()
ist hässlich und schwer zu fassen, während die version mit expliziten Aufrufe ist straight-forward. Ich bin zufällig auf die letztere vorziehen.super()
call -- ohne Sie ist alles straight-forward.Hast du den Artikel gelesen, den Sie verlinken? Es nicht schließen, dass
super
sollte vermieden werden, aber das sollte man vorsichtig sein, seine Vorbehalte, wenn es zu benutzen. Diese Vorbehalte sind zusammengefasst die Artikel, obwohl, ich würde nicht einverstanden mit Ihren Vorschlägen.Der wichtigste Punkt des Artikels ist, dass Mehrfachvererbung können sich chaotisch, und
super
hilft nicht so viel, wie der Autor möchte. Jedoch multiple Vererbung ohnesuper
wird es oft noch komplizierter.Wenn Sie nicht tun, die mehrfache Vererbung
super
gibt Sie den Vorteil, dass jemand erbt von der Klasse hinzufügen können einfache Mixins in Verbindung und Ihre__init__
wäre richtig genannt. Denken Sie daran, rufen Sie immer die__init__
von der Superklasse, auch wenn Sie Erben vonobject
, und führen Sie alle verbleibenden Argumente (*a
und**kw
) zu. Wenn Sie den Aufruf von anderen Methoden von der übergeordneten Klasse verwenden auchsuper
, aber dieses mal verwenden, deren ordnungsgemäße Unterschrift, die Sie bereits kennen (d.h. sicherzustellen, dass Sie die gleiche Signatur in allen Klassen).Wenn Sie Mehrfachvererbung müsste man tiefer Graben als das, und wahrscheinlich wieder Lesen die gleichen Artikel mehr gezielt, um sich bewusst sein, der Vorsichtsmaßnahmen. Und es ist auch nur bei Mehrfachvererbung, wenn Sie könnten eine situation, wo ein expliziter Aufruf an die Eltern könnte besser sein, als
super
, aber ohne ein bestimmtes Szenario niemand kann Ihnen sagen, obsuper
verwendet werden soll oder nicht.Die einzige änderung in
super
in Python 3.x ist, dass Sie nicht brauchen, um explizit zu übergeben, der die aktuelle Klasse undself
zu. Dies machtsuper
mehr attraktiv, weil es würde bedeuten, dass kein hardcoding entweder die übergeordnete Klasse oder der aktuellen Klasse.@Sven Marnach:
Das problem mit deinem Beispiel ist, dass Sie mischen explizite Oberklasse ruft
B.__init__
undLogger.__init__
im Blogartikel mitsuper()
in B., die nicht funktionieren. Entweder Sie verwenden alle explizite Superklasse aufruft oder verwenden Siesuper()
auf alle Klassen. Wenn Siesuper()
Sie brauchen, um verwenden Sie es auf alle Klassen beteiligt sind, einschließlich Eine, die ich denke. Auch in deinem Beispiel denke ich, Sie könnte verwenden Sie die explizite Superklasse Anrufe in alle Klassen, ich.e verwenden SieA.__init__
in Klasse BWenn es keine diamond-Vererbung denke ich, dass super() nicht viel Vorteil. Das problem ist jedoch, dass Sie nicht im Voraus wissen, wenn Sie in eine Diamant-Vererbung in der Zukunft also in diesem Fall wäre es klug zu nutzen
super()
sowieso (aber verwenden Sie es dann konsequent). Sonst würden Sie am Ende mit zu ändern, alle Klassen zu einem späteren Zeitpunkt oder führen Sie in Probleme.super()
hat Nachteile. Sie können am Beispiel der Arbeit mitsuper()
, aber es wird wirklich hässlich, während es ist straight-forward mit expliziten Superklasse aufruft. Beachten Sie, dass es wird diamond erbschaft beteiligt, da beideA
undLogger
stammen ausobject
. Nochmal, mein Punkt ist, dasssuper()
sollte nicht als die standard-Art des Aufrufs Basis-Klasse Methoden.