2017-02-14 10 views
0

Vor kurzem habe ich ein Buch ich lesen, erwähnt er die MRO in Mehrfachvererbung und Beispielcode geben:Python Mehrfachvererbung Ausgabe Ausgabe

class A(object): 
    def __init__(self): 
     print "A" 
     super(A, self).__init__() 

class B(object): 
    def __init__(self): 
     print "B" 
     super(B, self).__init__() 

class C(A,B): 
    def __init__(self): 
     print "C" 
     A.__init__(self) 
     B.__init__(self) 

C() 

Ausgang:

C 
A 
B 
B 

Ich möchte wissen, warum diese geschehen?

Antwort

2

Dies geschieht, weil Sie direkte Konstruktoraufrufe und Anrufe über super mischen. Ihre Klassenhierarchie sollte entweder das eine oder das andere tun.

Genauer gesagt ist das MRO für die Klasse CC, A, B. Wenn Sie also in A's Konstruktor super(A, self).__init__() aufrufen, ruft das den Konstruktor für B auf, da BA in C's MRO erfolgreich ist. Mit anderen Worten, es ist innerhalb A 's Konstruktor, dass die erste B gedruckt wird.

Nebenbei, super(A, self) in Python 3 überflüssig ist. super() ist genug; Die Argumente sind deduced aus dem Kontext.

Weiterführende Literatur:

0

Ich habe Ihren Code Python3 (von print-print() Ändern) umgewandelt, und fügte einige weitere Tracing-Anweisungen:

class A(object): 
    def __init__(self): 
     print("A", type(self).__mro__) 
     super(A, self).__init__() 
     print("/A") 

class B(object): 
    def __init__(self): 
     print("B", type(self).__mro__) 
     super(B, self).__init__() 
     print("/B") 

class C(A,B): 
    def __init__(self): 
     print("C") 
     A.__init__(self) 
     print("ca/b") 
     B.__init__(self) 
     print("/C") 

C() 

Hier ist der Ausgang:

C 
A (<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>) 
B (<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>) 
/B 
/A 
ca/b 
B (<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>) 
/B 
/C 

am Ausgang suchen, können Sie den Anruf an die C.__init__ Methode sehen geschieht, und das Drucken ‚C‘. Es ruft dann A.__init__ direkt auf (was ein Fehler ist - verwenden Sie super!).

Der Anruf A.__init__ gibt seine Nachricht aus, einschließlich des Attributs __mro__. Sie können die Sequenz sehen: C -> A -> B -> Objekt. Dies ist wichtig, weil Aufrufe an super() innerhalb von A.__init__ sich auf die Klasse B beziehen. Auch Aufrufe an super von innen C.__init__ hätten A.__init__ automatisch aufgerufen, wenn Sie sie zulassen.

Die nächste Methode, B.__init__, wird von der super Referenz innerhalb A.__init__, wie erwähnt, aufgerufen. Es ruft vermutlich Object.__init__ an, die nichts ausdruckt. ;-)

Sowohl B.__init__ und A.__init__ Rückkehr sehen wir den Mittelpunkt Nachricht ca/b, und dann direkten Aufruf an B.__init__ wird. Es wird eine Nachricht ausgedruckt, aber wieder ein Verweis auf super Formular B.__init__ tut nichts, denn B ist am Ende des MRO.

Der super() Mechanismus kann mit all diesen MRO-Sachen für Sie umgehen. Sie sollten A.__init__(self) nicht aufrufen müssen. Stattdessen können Sie nur super Griff es lassen, innen C.__init__, aber dies zu tun:

class C(A,B): 
    def __init__(self): 
     print("C") 
     super(C, self).__init__() 
+0

, die so groß ist! Vielen Dank – TreeCatCat