Короткий ответ
MRO — это детерминированный порядок, в котором Python ищет метод или атрибут по цепочке классов при множественном наследовании, вычисляемый по алгоритму C3-линеаризации; узнать точный порядок для конкретного класса можно через ClassName.__mro__ или ClassName.mro().
Как это работает подробнее
C3-линеаризация строит порядок так, чтобы класс всегда шёл раньше своих родителей, а относительный порядок родителей, указанных в определении класса, сохранялся — это даёт единый непротиворечивый порядок обхода даже для сложных диаграмм наследования. super() внутри метода использует именно этот порядок, переходя к следующему классу в MRO текущего экземпляра, а не напрямую к "родителю" в обычном понимании.
Пример кода
example.py
class Base:
def greet(self):
return "Base"
class MixinA(Base):
def greet(self):
return "A->" + super().greet()
class MixinB(Base):
def greet(self):
return "B->" + super().greet()
class Combined(MixinA, MixinB):
pass
print([c.__name__ for c in Combined.__mro__])
# ['Combined', 'MixinA', 'MixinB', 'Base', 'object']
print(Combined().greet()) # A->B->Base — порядок строго по MROЧто использовать на практике
- Практика. Понимание MRO важно для классов-миксинов (mixin), где функциональность собирается из нескольких небольших классов: порядок перечисления родителей в
class Combined(MixinA, MixinB, Base):определяет, какая реализация метода будет вызвана первой. При конфликтных иерархиях Python может поднятьTypeError: Cannot create a consistent method resolution order, если линеаризация невозможна.
Подводные камни
- Риски. Предполагают, что методы ищутся строго "слева направо" без учёта общих базовых классов, и не понимают, почему вызов через
super()в миксине неожиданно попадает не в прямого родителя, а в другой класс по MRO. Также злоупотребляют глубоким множественным наследованием, из-за чего реальный порядок вызовов становится трудно предсказать без явной проверки__mro__.