Python Schoolby trefilov
Шаг 1 из 4+140 XP

MRO и C3

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

MRO и алгоритм C3

MRO (Method Resolution Order) — порядок, в котором Python ищет атрибуты и методы при множественном наследовании. Когда ты пишешь obj.method(), интерпретатор перебирает классы по списку cls.__mro__ слева направо и берёт первый, где метод найден. Алгоритм построения этого списка — C3-линеаризация — гарантирует три свойства: дочерний идёт раньше родителей, порядок баз сохраняется, а каждый класс встречается ровно один раз.

Как читается

class A: pass
class B(A): pass
class C(A): pass
class D(B, C): pass

print(D.__mro__)

(D, B, C, A, object)

C3 идёт по слиянию (merge) линеаризаций родителей: L[D] = D + merge(L[B], L[C], [B,C]). На каждом шаге выбирается «голова» того списка, которой нет в «хвостах» других. Если корректного порядка не существует (например, class X(B, A) где A базовый для B), Python поднимает TypeError: Cannot create a consistent method resolution order.

Пример: алмаз с super()

class A:
    def hi(self): print("A")
class B(A):
    def hi(self): print("B"); super().hi()
class C(A):
    def hi(self): print("C"); super().hi()
class D(B, C):
    def hi(self): print("D"); super().hi()

D().hi()

D, B, C, A — каждый класс выполнен ровно раз благодаря MRO

Когда полезно знать / подводные камни

👍 Mixin-архитектура (Django views, DRF), кооперативные super()-цепочки, понимание, почему super() без аргументов «угадывает» правильный класс.
👎 Если в иерархии есть классы, не вызывающие super(), цепочка обрывается. Любое изменение порядка баз в class D(C, B) меняет MRO и поведение программы — это «дальнодействующая» правка. При сложных деревьях смотри Klass.__mro__ или Klass.mro() в дебаге.