Antworten:
Folgen...:
>>> class A(object): pass
...
>>> A.__mro__
(<class '__main__.A'>, <type 'object'>)
>>> class B(A): pass
...
>>> B.__mro__
(<class '__main__.B'>, <class '__main__.A'>, <type 'object'>)
>>> class C(A): pass
...
>>> C.__mro__
(<class '__main__.C'>, <class '__main__.A'>, <type 'object'>)
>>>
Solange wir eine einzelne Vererbung haben, __mro__
ist dies nur das Tupel von: der Klasse, ihrer Basis, der Basis ihrer Basis usw. bis object
(funktioniert natürlich nur für Klassen neuen Stils).
Jetzt mit Mehrfachvererbung ...:
>>> class D(B, C): pass
...
>>> D.__mro__
(<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <type 'object'>)
... Sie erhalten auch die Gewissheit, dass in __mro__
keine Klasse dupliziert wird und keine Klasse nach ihren Vorfahren kommt, außer dass Klassen, die zuerst auf derselben Ebene der Mehrfachvererbung eingegeben werden (wie B und C in diesem Beispiel), in der __mro__
links nach rechts.
Jedes Attribut, das Sie auf der Instanz einer Klasse erhalten, nicht nur Methoden, wird konzeptionell entlang der nachgeschlagen. __mro__
Wenn also mehr als eine Klasse unter den Vorfahren diesen Namen definiert, erfahren Sie, wo sich das Attribut befindet - in der ersten Klasse in das __mro__
, das diesen Namen definiert.
mro
kann durch eine Metaklasse angepasst werden, wird bei der Klasseninitialisierung einmal aufgerufen und das Ergebnis wird in gespeichert __mro__
- siehe docs.python.org/library/… .
mro()
steht für Method Resolution Order. Es gibt eine Liste der Typen zurück, von denen die Klasse abgeleitet ist, in der Reihenfolge, in der nach Methoden gesucht wird.
mro () oder __mro__ funktioniert nur bei neuen Stilklassen . In Python 3 funktionieren sie ohne Probleme. In Python 2 müssen diese Klassen jedoch erben object
.
Dies würde vielleicht die Reihenfolge der Auflösung zeigen.
class A(object):
def dothis(self):
print('I am from A class')
class B(A):
pass
class C(object):
def dothis(self):
print('I am from C class')
class D(B, C):
pass
d_instance= D()
d_instance.dothis()
print(D.mro())
und Antwort wäre
I am from A class
[<class '__main__.D'>, <class '__main__.B'>, <class '__main__.A'>, <class '__main__.C'>, <class 'object'>]
Die Regel lautet "Tiefe zuerst", was in diesem Fall D, B, A, C bedeuten würde.
Python verwendet normalerweise eine Tiefen-First- Reihenfolge bei der Suche nach ererbenden Klassen. Wenn jedoch zwei Klassen von derselben Klasse erben, entfernt Python die erste Erwähnung dieser Klasse aus mro.
Die Reihenfolge der Auflösung unterscheidet sich in der Diamantvererbung.
class A(object):
def dothis(self):
print('I am from A class')
class B1(A):
def dothis(self):
print('I am from B1 class')
# pass
class B2(object):
def dothis(self):
print('I am from B2 class')
# pass
class B3(A):
def dothis(self):
print('I am from B3 class')
# Diamond inheritance
class D1(B1, B3):
pass
class D2(B1, B2):
pass
d1_instance = D1()
d1_instance.dothis()
# I am from B1 class
print(D1.__mro__)
# (<class '__main__.D1'>, <class '__main__.B1'>, <class '__main__.B3'>, <class '__main__.A'>, <class 'object'>)
d2_instance = D2()
d2_instance.dothis()
# I am from B1 class
print(D2.__mro__)
# (<class '__main__.D2'>, <class '__main__.B1'>, <class '__main__.A'>, <class '__main__.B2'>, <class 'object'>)
class B3
aber im zweiten Fall geht es class A
nachclass B1