Следуйте по ... ... *
>>> 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'>)
>>>
Пока у нас есть единственное наследование, __mro__
- это просто кортеж: класса, его базы, базы его базы и т. Д. До object
(конечно, работает только для классов нового стиля).
Теперь, с множественным наследованием ...:
>>> class D(B, C): pass
...
>>> D.__mro__
(<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <type 'object'>)
... вы также получаете гарантию, что в __mro__
ни один класс не дублируется, и ни один класс не идет после своих предков, за исключением того, что классы, которые сначала входят на один и тот же уровень множественного наследования (как B и C этот пример) находятся в __mro__
слева направо.
Каждый атрибут, который вы получаете в экземпляре класса, а не только в методах, концептуально ищется вдоль __mro__
, поэтому, если более одного класса среди предков определяет это имя, это говорит вам, где будет найден атрибут - - в первом классе в __mro__
, который определяет это имя.