Odpowiedzi:
Idź dalej ...:
>>> 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'>)
>>>
Dopóki mamy pojedyncze dziedziczenie, __mro__
jest to po prostu krotka: klasa, jej baza, jej baza itd., Aż do object
(oczywiście działa tylko dla klas w nowym stylu).
Teraz z dziedziczeniem wielokrotnym ...:
>>> class D(B, C): pass
...
>>> D.__mro__
(<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <type 'object'>)
... zyskujesz również pewność, że w programie __mro__
żadna klasa nie jest zduplikowana i żadna klasa nie występuje po swoich przodkach, poza tym, że klasy, które jako pierwsze wchodzą na ten sam poziom dziedziczenia wielokrotnego (jak B i C w tym przykładzie) znajdują się w __mro__
z lewej na prawą.
Każdy atrybut, który otrzymujesz w instancji klasy, a nie tylko metody, jest koncepcyjnie przeglądany wzdłuż __mro__
, więc jeśli więcej niż jedna klasa wśród przodków definiuje tę nazwę, to mówi ci, gdzie zostanie znaleziony atrybut - w pierwszej klasie w __mro__
który definiuje tę nazwę.
mro
można dostosować za pomocą metaklasy, jest wywoływana raz podczas inicjalizacji klasy, a wynik jest przechowywany w __mro__
- patrz docs.python.org/library/… .
mro()
oznacza Method Resolution Order. Zwraca listę typów, z których pochodzi klasa, w kolejności wyszukiwania metod.
mro () lub __mro__ działa tylko na nowych klasach stylów. W Pythonie 3 działają bez żadnych problemów. Ale w Pythonie 2 te klasy muszą dziedziczyć z object
.
To być może pokazałoby kolejność rozdzielczości.
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())
a odpowiedź byłaby
I am from A class
[<class '__main__.D'>, <class '__main__.B'>, <class '__main__.A'>, <class '__main__.C'>, <class 'object'>]
Reguła jest głębi, co w tym przypadku oznaczałoby D, B, A, C.
Python zwykle używa kolejności od początku do głębi podczas wyszukiwania klas dziedziczących, ale gdy dwie klasy dziedziczą z tej samej klasy, Python usuwa pierwszą wzmiankę o tej klasie z mro.
Kolejność rozdzielczości będzie inna w przypadku dziedziczenia diamentów.
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
ale w drugim przypadku idzie class A
poclass B1