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 Firstnie 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 Firstdziedziczy 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 Thirdbyć 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.