Skip to content

Latest commit

 

History

History
148 lines (84 loc) · 4.19 KB

File metadata and controls

148 lines (84 loc) · 4.19 KB

Что такое MRO вообще

MRO (Method Resolution Order) — это просто правила, по которым Python ищет методы и атрибуты у объектов в иерархии классов.

  • Когда ты вызываешь obj.method(), Python должен понять в каком классе искать method.

  • Если классов несколько (множественное наследование), может быть несколько кандидатов. MRO решает в каком порядке проверять классы, чтобы не запутаться.

По сути: MRO — это список классов, по которому Python идёт сверху вниз, пока не найдёт нужный метод.


2️⃣ Зачем оно нужно

Простой пример:

class A:
    def say(self):
        print("A")

class B(A):
    def say(self):
        print("B")

class C(A):
    def say(self):
        print("C")

class D(B, C):
    pass

d = D()
d.say()

Что напечатает d.say()?

  • Интуитивно: Python должен выбрать между B и C.

  • Тут вступает в силу MRO.

Можно посмотреть:

print(D.__mro__)`

Выведет что-то вроде:

(<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>)

То есть Python ищет метод в порядке: D → B → C → A → object.

  • D ничего не имеет, идём дальше.

  • B имеет say → берём отсюда.

Именно поэтому печатает "B".

💡 Если бы MRO была другой, могло бы печатать "C" или "A".


3️⃣ Как Python считает MRO

Python использует алгоритм C3-линеаризации.

  • Он гарантирует: порядок поиска сначала родитель слева, потом справа, но при этом сохраняется порядок, определённый классами.

  • Это важно, чтобы избежать конфликтов при множественном наследовании.

Пример простого множественного наследования:

class X: pass
class Y: pass
class Z(X, Y): pass

MRO для ZZ → X → Y → object.

  • Сначала проверяем Z, потом левый родитель X, потом правый Y, потом object.

4️⃣ Когда реально помогает

  1. Множественное наследование: без MRO ты бы не знал, какой метод выберется.

  2. super(): когда вызываешь super().method(), Python идёт по MRO.

    • Это ключевой момент, особенно при цепочках вызовов.

Пример со super():

class A:
    def hello(self):
        print("A")
        
class B(A):
    def hello(self):
        print("B")
        super().hello()

class C(A):
    def hello(self):
        print("C")
        super().hello()

class D(B, C):
    def hello(self):
        print("D")
        super().hello()

D().hello()

Вывод:

D B C A

  • super() не всегда идёт просто к родителю, а идёт по MRO → поэтому порядок B → C → A совпадает с MRO.

🔑 Ключевая мысль

MRO — это "карта" для Python, чтобы найти методы и атрибуты в сложных иерархиях классов и правильно работал super().
Без MRO: множественное наследование было бы хаотичным, супер() не работал бы предсказуемо, методы могли бы неожиданно перезаписываться.

[[IT]] [[Python]]