Получить доступ

Как работают наследование, super() и MRO?

JuniorООП
Ещё спрашивают так:
  • Что такое MRO в Python?
  • Как работает множественное наследование?
  • Что делает super()?
  • Что такое ромбовидное наследование?
Коротко

MRO — порядок, в котором Python ищет метод по иерархии классов; super() вызывает следующий класс в MRO.

  • MRO строится алгоритмом C3, смотреть: Class.__mro__ или Class.mro()
  • super() — не «родитель», а следующий по MRO; это важно при множественном наследовании

А ещё Ромб решается тем, что общий предок в MRO встречается один раз

Так подсказку видит пользователь sotto на живом собеседовании — за пару секунд, пока вы думаете вслух.

Подробно

При наследовании класс получает атрибуты и методы родителей и может их переопределить. Когда вызывается метод, Python ищет его по MRO (method resolution order) — линейному списку классов: сам класс, затем родители, в конце object.

При множественном наследовании MRO строится алгоритмом C3. Он гарантирует, что класс идёт раньше своих родителей, порядок родителей из объявления сохраняется, и каждый класс встречается один раз. Поэтому «ромб» (B и C наследуют A, D наследует B и C) не вызывает метод A дважды: MRO будет D, B, C, A, object.

super() возвращает объект, который ищет методы, начиная со следующего класса после текущего в MRO того объекта, для которого вызван метод. Поэтому в B.__init__ вызов super().__init__() при создании D пойдёт в C, а не сразу в A. Это позволяет строить «кооперативное» наследование: каждый класс вызывает super(), и вся цепочка отрабатывает по одному разу.

На практике множественное наследование используют для миксинов — небольших классов с одной добавкой поведения.

Пример

class A:
    def hello(self):
        return "A"

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

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

class D(B, C):
    pass

D.__mro__     # (D, B, C, A, object)
D().hello()   # 'BCA' — super() в B ведёт в C, а не в A

Что хотят услышать

  • Определение MRO и как его посмотреть.
  • super() — следующий в MRO, а не просто родитель.
  • Как решается ромбовидное наследование.
  • Применение: миксины, кооперативные __init__.

Частые ошибки

  • Утверждать, что super() всегда вызывает непосредственного родителя.
  • Вызывать родителя напрямую (A.__init__(self)) в множественном наследовании — метод может выполниться дважды.

Что спросят дальше

Связанные вопросы

Закрытая бета

Подсказки на собеседовании — в реальном времени

sotto слышит вопрос интервьюера и показывает короткий ответ и план, как в блоке «Коротко». Оставьте контакт — пришлём доступ и промокод.

  • Промокод на 2 часа — сверх пробных 30 минут
  • Программа для Windows — скачать сразу, войти — через Яндекс ID или VK ID
  • Прямая связь с разработчиком: что улучшить — сделаем