Множественное, многоуровневое наследование и порядок разрешения методов (MRO) в Python
Множественное наследование в Python
Python позволяет классу наследовать от более чем одного базового класса, как и C++. Эта возможность называется множественным наследованием и даёт производному классу комбинировать поведение нескольких родительских классов.
Синтаксис зеркалит одиночное наследование: вы перечисляете все родительские классы в скобках, разделённых запятыми.
Пример
class Base1:
pass
class Base2:
pass
class MultiDerived(Base1, Base2):
pass
В этом примере MultiDerived наследует атрибуты и методы от Base1 и Base2.

Диаграмма: MultiDerived получает черты от Base1 и Base2.
Многоуровневое наследование в Python
За пределами двух уровней можно строить цепочки наследования: класс наследует от производного класса, создавая многоуровневое наследование. Python поддерживает любую глубину.
Каждый новый производный класс наследует от своего непосредственного родителя, перенося также атрибуты предков.
Пример:
class Base:
pass
class Derived1(Base):
pass
class Derived2(Derived1):
pass
Здесь Derived1 расширяет Base, а Derived2 дальше расширяет Derived1, образуя трёхзвенную цепочку.

Порядок разрешения методов (MRO) в Python
Каждый класс Python в конечном итоге наследует от object, универсального базового типа. Следовательно, все объекты являются экземплярами object, будь то встроенные или пользовательские:
# Вывод: True
print(issubclass(list, object))
# Вывод: True
print(isinstance(5.5, object))
# Вывод: True
print(isinstance("Hello", object))
При множественном наследовании Python разрешает атрибуты с помощью обхода в глубину, слева направо, без повторного посещения класса. Этот порядок обхода называется Method Resolution Order (MRO) и гарантирует, что класс появляется перед своими родителями.
MRO для MultiDerived: [MultiDerived, Base1, Base2, object]. Его можно просмотреть через атрибут __mro__ или метод mro():
MultiDerived.__mro__
# (<class '__main__.MultiDerived'>, <class '__main__.Base1'>, <class '__main__.Base2'>, <class 'object'>)
MultiDerived.mro()
# [<class '__main__.MultiDerived'>, <class '__main__.Base1'>, <class '__main__.Base2'>, <class 'object'>]
Сложные графы наследования следуют тому же принципу. Рассмотрим пример:

# Демонстрация MRO
class X: pass
class Y: pass
class Z: pass
class A(X, Y): pass
class B(Y, Z): pass
class M(B, A, Z): pass
print(M.mro())
# Вывод:
# [<class '__main__.M'>, <class '__main__.B'>, <class '__main__.A'>, <class '__main__.X'>, <class '__main__.Y'>, <class '__main__.Z'>, <class 'object'>]
Для глубокого изучения алгоритма расчёта MRO обратитесь к официальной документации Python о наследовании классов и обсуждению MRO.
Python
- Освоение типов данных в Python: практическое руководство
- Мастерство операторов Python: Полное руководство
- Оператор pass в Python: практическое руководство
- Словари в Python: создание, манипуляции и продвинутые техники
- Пользовательские исключения в Python: практическое руководство
- Объектно-ориентированное программирование в Python: классы, наследование, инкапсуляция и полиморфизм
- Наследование в Python: концепции, синтаксис и практические примеры
- Понимание type() и isinstance() в Python: практические примеры
- Наследование в C#: базовые и производные классы, интерфейсы
- Объектно-ориентированное программирование в Python: полное руководство