метод разрешения порядка MRO - PullRequest
2 голосов
/ 15 апреля 2019

Почему после поиска B он не углубляется в поиск Y ИЛИ z, а ищет поиск A?

Y является родителем A, если сначала должен искать A, но Y является родителем B, поэтому он должен искать Y первым, почему это не вызывает ошибку MRO?

Может кто-нибудь объяснить, как работает этот поиск?

class X(object):pass
class Y(object): pass
class Z(object): pass
class A(X,Y): pass
class B(Y,Z):pass
class M(B,A,Z):pass
print M.__mro__

дает

(<class '__main__.M'>, <class '__main__.B'>, <class '__main__.A'>, <class '__main__.X'>, <class '__main__.Y'>, <class '__main__.Z'>, <type 'object'>)

enter image description here

1 Ответ

1 голос
/ 15 апреля 2019

В вашем конкретном примере после поиска 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
...