MRO или Method Resolution Order в Python
Что такое MRO
MRO - Это порядок разрешения методов и о нем обычно говорят, когда речь заходит о множественном наследовании (кстати, если с ним не знакомы, настоятельно рекомендую немного покопаться в теме).
Он определяет последовательность, по которой Python ищет методы и атрибуты в классе и его родителях. Чтобы чуть глубже понять, предлагаю рассмотреть принцип его работы на конкретном примере.
Разбираемся с MRO на примере
Допустим, у нас есть некий класс D, который наследуется от классов B и C, которые наследуются от класса A, который ... :) пожалуй, остановимся на этом.
У этих классов определены методы who_am_i
, которые просто печатают имя класса, которому они принадлежат. Классу D мы не будем создавать этот метод, а сделаем из него просто класс-заглушку:
class A: def who_am_i(self): print("A") class B(A): def who_am_i(self): print("B") class C(A): def who_am_i(self): print("C") class D(B, C): ...
Теперь создадим экземпляр класса D
и попробуем вызвать у него метод who_am_i
:
d = D() d.who_am_i()
Что произойдет? А вот что. В выводе мы увидим:
>>> B
Почему именно B
, нам может рассказать MRO. Для удобства можно просто вызвать метод mro()
или атрибут __mro__
:
print(D.mro()) # или: print(D.__mro__) >>> (<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>)
Из вывода консоли можно увидеть порядок обращений. Сначала метод ищется в классе D
, но его там нет, поэтому Python смотрит в следующем классе - B
. Метод who_am_i
есть у класса B
, поэтому именно он и вызывается. Соответственно, при печати мы и видим B
.
Почему MRO работает именно так?
Во всем виновата линеаризация и конкретно алгоритм C3 linearization
. Разберем кратко, что это такое.
Линеаризация – это упорядочение классов (включая сам класс и его родителей) в список, отсортированный в порядке их "Удаленности". Этот список Python использует для поиска методов и атрибутов. А алгоритм C3 определяет три главные особенности такого порядка:
Почитать подробнее и ознакомиться с примерами можно на Вики
Таким образом, MRO определяет, как Python ищет методы и атрибуты в классах при множественном наследовании, делая этот процесс предсказуемым и логичным.