В вашем конкретном примере после поиска B
мы не можем сразу рассмотреть Y
, потому что это дочерний элемент A
. Мы не можем сразу рассмотреть Z
, потому что M
наследуется от A
до , наследуется от Z
.
Python использует порядок разрешения метода C3 подробности здесь .
Порядок разрешения C3 хорошо решает проблему наследования алмазов
В приведенном ниже примере у нас есть очень общий класс Object
, который является суперклассом B
и C
. Мы только хотим, чтобы реализации методов (скажем, __repr__
или что-то еще) в Object
рассматривались, если ни B
, ни C
не имеют реализации.
Object
/ \
B C
\ /
A
Другими словами, каждый возможный родительский элемент в транзитивном замыкании родительских классов A
рассматривается, но классы упорядочены в соответствии с «последним» путем от базового класса к классу. под вопросом.
Есть два пути к object
:
A -> B -> Object
A -> C -> Object
"Последний" путь - A -> C -> Object
, потому что A -> B -> Object
был бы раньше при левостороннем смещении поиска в глубину.
C3 линеаризация удовлетворяет двум ключевым инвариантам:
- если
X
наследуется от Y
, X
проверяется перед Y
.
- если
Z
наследуется от U
, а затем V
в этом порядке , U
проверяется перед V
.
Действительно, C3
линеаризация гарантирует, что оба эти свойства выполняются.
Можно построить иерархии, которые не могут быть линеаризованы, и в этом случае вы получите исключение во время определения класса.
работает inherit.py
class E: pass
class F: pass
class A(E, F): pass
class B(F, E): pass
class Z(A, B): pass
выдает следующую ошибку.
Traceback (most recent call last):
File "inherit.py", line 5, in <module>
class Z(A, B): pass
TypeError: Cannot create a consistent method resolution
order (MRO) for bases E, F