Jest to szczegółowo opisane z rozsądną ilością szczegółów przez samego Guido w jego blogu Order Resolution Resolution Order (w tym dwie wcześniejsze próby).
W twoim przykładzie Third()
zadzwoni First.__init__
. Python szuka każdego atrybutu w rodzicach klasy, ponieważ są one wymienione od lewej do prawej. W tym przypadku szukamy __init__
. Jeśli więc zdefiniujesz
class Third(First, Second):
...
Python zacznie od patrzenia First
, a jeśli First
nie ma atrybutu, to będzie patrzył Second
.
Ta sytuacja staje się bardziej złożona, gdy dziedziczenie zaczyna przecinać ścieżki (na przykład, jeśli First
dziedziczy się Second
). Przeczytaj powyższy link, aby uzyskać więcej szczegółów, ale w skrócie, Python spróbuje utrzymać kolejność, w jakiej każda klasa pojawia się na liście dziedziczenia, poczynając od samej klasy potomnej.
Na przykład, jeśli miałeś:
class First(object):
def __init__(self):
print "first"
class Second(First):
def __init__(self):
print "second"
class Third(First):
def __init__(self):
print "third"
class Fourth(Second, Third):
def __init__(self):
super(Fourth, self).__init__()
print "that's it"
MRO byłoby [Fourth, Second, Third, First].
Nawiasem mówiąc: jeśli Python nie może znaleźć spójnej kolejności rozwiązywania metod, zgłosi wyjątek, zamiast wracać do zachowania, które może zaskoczyć użytkownika.
Edytowano, aby dodać przykład niejednoznacznego MRO:
class First(object):
def __init__(self):
print "first"
class Second(First):
def __init__(self):
print "second"
class Third(First, Second):
def __init__(self):
print "third"
Powinien Third
być MRO [First, Second]
lub [Second, First]
? Nie ma oczywistych oczekiwań, a Python zgłosi błąd:
TypeError: Error when calling the metaclass bases
Cannot create a consistent method resolution order (MRO) for bases Second, First
Edycja: Widzę kilka osób argumentujących, że w powyższych przykładach brakuje super()
wywołań, więc pozwól mi wyjaśnić: celem przykładów jest pokazanie, jak zbudowana jest MRO. Są one nie przeznaczone do drukowania „first \ nsecond \ trzecia” lub cokolwiek innego. Możesz - i oczywiście powinieneś bawić się przykładem, dodawać super()
połączenia, sprawdzać, co się dzieje, i lepiej rozumieć model dziedziczenia Pythona. Ale moim celem tutaj jest uproszczenie i pokazanie, jak zbudowano MRO. I jest zbudowany, jak wyjaśniłem:
>>> Fourth.__mro__
(<class '__main__.Fourth'>,
<class '__main__.Second'>, <class '__main__.Third'>,
<class '__main__.First'>,
<type 'object'>)
super()
można z niego skorzystać. Nie polecałbym używania go z klasami wykorzystującymi dziedziczenie liniowe, gdzie jest to po prostu bezużyteczny narzut.