Unterschied zwischen super() aufrufen und Oberklasse direkt
In Python 2.7 und 3, verwende ich folgende Methode aufrufen, eine super-Klasse-Funktion:
class C(B):
def __init__(self):
B.__init__(self)
Ich sehe es auch möglich, zu ersetzen B.__init__(self)
mit super(B, self).__init__()
und in Python ist3 super().__init__()
.
Gibt es irgendwelche Vorteile oder Nachteile, dies zu tun oder so? Es macht mehr Sinn, zu rufen es von B
direkt für mich zumindest, aber vielleicht gibt es einen guten Grund, wo super()
können nur verwendet werden, wenn Sie Metaklassen (die ich im Allgemeinen zu vermeiden).
InformationsquelleAutor johannestaas | 2014-02-07
Du musst angemeldet sein, um einen Kommentar abzugeben.
Für einfachvererbung,
super()
ist nur ein schicker Weg, um beziehen sich auf den Basistyp. Auf diese Weise, Sie machen den code besser wartbar, zum Beispiel in Fall, dass Sie wollen, ändern Sie den Basistyp der name. Wenn Sie mitsuper
überall, Sie brauchen nur zu ändern ist es in derclass
Linie.Der wirkliche Vorteil kommt mit Mehrfachvererbung obwohl. Bei der Verwendung von
super
, mit einem einzigen Aufruf wird nicht nur automatisch aufrufen der Methode von alle Basis-Typen (in der richtigen Vererbung Reihenfolge), aber es wird auch sicherzustellen, dass jede Methode nur einmal aufgerufen.Dieser ermöglicht im Grunde Typen haben eine Diamant Eigenschaft, z.B. Sie haben einen einzigen Basistyp
A
, und zwei ArtenB
undC
die beiden stammen ausA
. Und dann haben Sie eine ArtD
was erbt von beidenB
undC
(und damit implizit Erben vonA
zu—und das gleich zweimal). Wenn Sie rufen Sie die Basis-Typen " Methoden explizit jetzt, werden Sie am Ende den Aufruf Einer Methode zweimal. Aber mitsuper
es wird nur rufen Sie es einmal:Wenn wir jetzt instanziieren
D
ist, erhalten wir die folgende Ausgabe:Nun, lassen Sie uns alles tun, dass wieder mit manuell aufrufen der Basis-Typ der Methode:
- Und das ist die Ausgabe:
Wie Sie sehen können,
A2
zweimal vorkommt. Dies ist in der Regel nicht, was Sie wollen. Es wird noch chaotischer, wenn Sie manuell aufrufen, Methode einer Ihrer Basis-Typen, die verwendetsuper
. Also stattdessen sollten Sie nur verwendensuper()
um sicherzustellen, dass alles funktioniert, und auch so dass Sie nicht haben, um sorgen über zu viel.Sehr gutes Beispiel btw, danke 🙂 @poke
Ihr Verständnis ist teilweise richtig. Die Logik, die die Reihenfolge bestimmt, ist nicht wirklich ausgewertet, wenn
super()
genannt wird. Was die Reihenfolge basiert auf dem - Methode Auflösung Bestellen (MRO) in Python, die im Grunde ist eine konsistente Linearisierung der Typ-Hierarchie. Sie können sehen, die Instandhaltung vonD
suchen Sie inD.__mro__
die im GrundeD, C, B, A, object
. Leider, die Berechnung der MRO richtig ist ein wenig komplexer; es nutzt die C3-Linearisierung-Algorithmus. Aber vereinfacht, Ihr Modell zu "sehen" funktioniert.Was
super()
tut aber nicht berechnen, der nächste Schritt aber einfach zu sagen, Python, weiter innerhalb des MRO. Das ist, warum alle Klassen, die Teil einer Hierarchie verwenden solltensuper()
, und das ist, warumA
Anrufesuper()
. Wenn Sie hinzufügen, eine andere Artclass X(object)
, und machteD
auch Erben, dann würden Sie sehen, dass ohneA
'ssuper()
,X
würde nicht aufgerufen werden. DaX
kommt nachA
im MRO, dersuper()
erforderlich ist, um zu sagen, Python, weiterhin in die Instandhaltung.Ich bin mir nicht sicher, was du meinst mit.. Der MRO-berechnet mit Algorithmus (das wirklich sehr kompliziert ist; siehe das Beispiel auf Wikipedia). Sobald die MRO berechnet, die
super()
fordert, rufen die Typen in dieser Reihenfolge. Und natürlich, dasuper()
sind Funktionsaufrufe, danach kehrt es in das Gegenteil um; aber das ist nur der stack aufrufen.InformationsquelleAutor poke