python Mehrfachvererbung von verschiedenen Pfaden mit derselben Methode name
Mit dem folgenden code-Beispiel, kann super
verwendet werden, oder C
rufen A.foo
und B.foo
explizit?
class A(object):
def foo(self):
print 'A.foo()'
class B(object):
def foo(self):
print 'B.foo()'
class C(A, B):
def foo(self):
print 'C.foo()'
A.foo(self)
B.foo(self)
InformationsquelleAutor der Frage sayap | 2010-09-28
Du musst angemeldet sein, um einen Kommentar abzugeben.
super()
nur jemals lösen einer einzigen Klasse-Typ für eine bestimmte Methode, so dass, wenn Sie Erben von mehreren Klassen und möchten, rufen Sie die Methode in beiden von Ihnen, müssen Sie es explizit tun.InformationsquelleAutor der Antwort Amber
super
ist ja bestimmt für diese situation, aber es funktioniert nur, wenn Sie diese konsequent nutzen. Wenn der Basis-Klassen nicht auch alle nutzensuper
es wird nicht funktionieren, es sei denn, die Methode ist inobject
Sie haben, um so etwas wie eine gemeinsame Basis-Klasse zu beenden, die Kette dersuper
Anrufe.@Marcin fragt, warum es eine gemeinsame Basis:
Ohne
FooBase
implementiertfoo
aber nicht nennensuper()
die Letzte Klasse, die nenntsuper()
erhalten ein Attribut Fehler, da es keine Basis-Methode aufrufen.Wenn es separate Basis-Klassen
class A(AFooBase):
undclass B(BFooBase):
diesuper()
Anruf inA
nennen würde, die Methode inAFooBase
und die Methode inB
würde nie genannt werden. Wenn die Basis ist üblich für alle Klassen geht es am Ende der Methode Auflösung um und Sie können sicher sein, dass egal, wie die Klassen definiert werden, die Basis-Methode der Klasse wird die Letzte sein, genannt.InformationsquelleAutor der Antwort Duncan
Dank für alle, die dazu beigetragen zu diesem thread.
Zusammenfassen:
Die (derzeit) akzeptierte Antwort ist ungenau. Die korrekte Bezeichnung sollte sein: super() ist NICHT NUR gut für die Lösung einfacher Vererbung, ABER AUCH Mehrfachvererbung. Und der Grund ist gut erklärt in @blckknght 's Kommentar:
Den richtigen Weg, wie @duncan hingewiesenist die Verwendung von super(), aber verwenden Sie es konsequent.
Aber es lohnt sich auch zu betonen, dass die Methode aufrufen Reihenfolge scheint NICHT intuitiv, der erste Gedanke. Das Ergebnis ist:
Diese scheinbar seltsame bestellenDen eigentlichen Aufruf, um nochC, A, B
basierend auf MRO. In anderen Worten,Als eine Regel von Daumen, wenn Sie wollen, zu Reisen, um ALLE übergeordneten Methoden, aber nicht wirklich wichtig, die invoke-Bestellung, verwenden Sie
super()
consisently. Andernfalls können Sie wählen, um explizite Aufruf von parent-Methoden in einer bestimmten Reihenfolge.Nicht mischen, die Verwendung von super() und die explizite Berufung aber. Sonst werden Sie am Ende böse überschneidungen, wie bereits erwähnt, in diese Antwort.
UPDATE: Wenn Sie wollen, um zu Tauchen tiefer...
Kurz, mit
super(...)
konsequent in der ganzen Klasse-Familie wird dafür sorgen, ALLE gleichnamigen Methoden aus Vorfahren, die einmal aufgerufen, in der Reihenfolge der MRO. Solche call-ALL-Vorfahren (statt rufen Sie-nur-die-erste-Kandidaten) Verhalten kann begrifflich leichter zu akzeptieren, wenn die Methode, die passiert zu sein eine__init__()
siehe das Beispiel in diesem blog-post.Sagen: "Folgen Sie dem MRO, um" vielleicht nicht sehr präzise, aber. Es eigentlich immer nach dem "Enkel" 's MRO, irgendwie. Es ist faszinierend zu sehen, Sie in Aktion. Das Ergebnis folgenden Programm möglicherweise nicht genau das, was Sie dachte, es wäre. Achten Sie darauf, wie
A.__mro__
bleibt die gleiche in 2 verschiedenen Aufruf-stack, aber wiesuper(A, self).name
odersuper(A, self).foo()
sich ANDERS Verhalten, ausgelöst durchA().foo()
und durchC().foo()
. Das Ergebnis zitiert am Ende.Und das Ergebnis von Python 2.7.12 ist:
InformationsquelleAutor der Antwort RayLuo
Super-aufrufen, die
foo
Methode auf die "erste" super-Klasse. Dieses basiert auf der Methode Auflösung Um (__mro__
) für die KlasseC
.Daher, wenn Sie anrufen
super(C, self).foo()
A.foo
genannt wird. Wenn Sie die Vererbung, umclass C(B, A):
dann ist dies Umgekehrt. Die__mro__
jetzt aussieht:Wenn Sie anrufen
super(C, self).foo()
nach dieser änderungB.foo()
wird aufgerufen.InformationsquelleAutor der Antwort Manoj Govindan
Wenn Sie Hinzugefügt haben, die folgenden:
Dann super(C, selbst).foo() bezieht sich auf A. foo
Die Ausgabe ist
[Edit: zusätzliche Informationen und links]
InformationsquelleAutor der Antwort pyfunc
Wie Duncan oben gesagt, kann man vorhersehbare Ergebnisse, vor allem, wenn Sie super() konsequent.
Die Ergebnisse der folgenden Tests waren hilfreich für mich:
Diesem heraus gedruckt wird:
InformationsquelleAutor der Antwort bmzf
Dies ist möglich mit
super
InformationsquelleAutor der Antwort acktus