← Назад к вопросам

Какой порядок разрешения доступа к атрибутам при множественном наследовании в Python?

1.8 Middle🔥 171 комментариев
#Python Core

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Порядок разрешения доступа (MRO — Method Resolution Order)

В Python при множественном наследовании используется алгоритм C3 линеаризация для определения порядка поиска методов и атрибутов. Это обеспечивает монотонность и предсказуемость наследования.

Алгоритм C3 линеаризации

Порядок обхода:

  1. Сам класс (самый левый)
  2. Левый родитель и его предки
  3. Правый родитель и его предки
  4. object (корневой класс)
class A:
    def method(self):
        return "A"

class B(A):
    pass

class C(A):
    def method(self):
        return "C"

class D(B, C):
    pass

# MRO: D -> B -> C -> A -> object
print(D.mro())
# [<class D>, <class B>, <class C>, <class A>, <class object>]

obj = D()
print(obj.method())  # "C" — найден в C, так как B не переопределяет

Как смотреть MRO

# Способ 1: метод mro()
print(MyClass.mro())

# Способ 2: атрибут __mro__
print(MyClass.__mro__)

# Способ 3: встроенная функция
print(inspect.getmro(MyClass))

Практический пример

class Animal:
    def sound(self):
        return "Some sound"

class Swimmer:
    def sound(self):
        return "Splash"

class Walker:
    def sound(self):
        return "Footsteps"

class Duck(Swimmer, Walker, Animal):
    pass

print(Duck.mro())
# [Duck, Swimmer, Walker, Animal, object]

duck = Duck()
print(duck.sound())  # "Splash" — найден в Swimmer (первый в MRO)

Правила C3 линеаризации

Порядок наследования в скобках имеет значение:

class X(A, B):  # A имеет приоритет
    pass

class Y(B, A):  # B имеет приоритет
    pass

Монотонность: если класс A предшествует B в MRO родителя, то A должен предшествовать B и в MRO класса.

Проблемы с наследованием

Вот это вызовет ошибку:

class A(B, C):
    pass

class D(C, B):  # Нарушает порядок!
    pass

# TypeError: Cannot create a consistent method resolution order

Правильно:

class A(B, C):
    pass

class D(A):  # Наследуемся от A, не переопределяем B и C
    pass

super() и MRO

Метод super() использует именно MRO для поиска следующего класса:

class Base:
    def __init__(self):
        print("Base init")

class Mixin:
    def __init__(self):
        print("Mixin init")
        super().__init__()

class Child(Mixin, Base):
    def __init__(self):
        print("Child init")
        super().__init__()

child = Child()
# Child init
# Mixin init
# Base init

Порядок вывода следует C3 MRO: Child -> Mixin -> Base -> object.

Итоги

  • MRO определяется алгоритмом C3 линеаризации
  • Поиск идёт слева направо по порядку наследования
  • super() работает с MRO для вызова методов родительских классов
  • Всегда проверяй MRO при множественном наследовании через .mro() или .__mro__
Какой порядок разрешения доступа к атрибутам при множественном наследовании в Python? | PrepBro