Множественное наследование в Python

В этом уроке вы узнаете о множественном наследовании в Python и том, как его использовать в своих программах. Вы также узнаете о многоуровневом наследовании и порядке разрешения методов.

Множественное наследование

Множественное наследование — это возможность класса иметь более одного родительского класса. 

При множественном наследовании дочерний класс наследует все свойства родительских классов. Синтаксис множественного наследования очень похож на синтаксис обычного наследования.

class Base1:
    pass

class Base2:
    pass

# этот класс наследует сразу от двух родительских классов: Base1 и Base2
class MultiDerived(Base1, Base2):
    pass

Многоуровневое наследование

Мы также можем наследовать класс от уже наследуемого. Это называется многоуровневым наследованием. Оно может иметь сколько угодно уровней.

В многоуровневом наследовании свойства родительского класса и наследуемого от него класса передаются новому наследуемому классу.

class Base:
    pass

class Derived1(Base):
    pass

class Derived2(Derived1):
    pass

Класс Derived1 наследуется от класса Base, а класс Derived2 — от класса Derived1.

Порядок разрешения методов (MRO)

Все классы в Python наследуются от класса object. Это базовый класс языка.

И поэтому технически все классы, встроенные или определенные пользователем, являются наследуемыми, а все объекты — экземплярами класса object.

# Вывод: True
print(issubclass(list,object))

# Вывод: True
print(isinstance(5.5,object))

# Вывод: True
print(isinstance("Привет",object))

По порядку разрешения методов любой указанный атрибут сначала ищется в объявленном классе. Если его там нет, поиск продолжается в родительских классах на максимальную глубину слева направо без прохода по одному классу дважды.

Например, в случае с классом MultiDerived порядок поиска будет следующим: [MultiDerived, Base1, Base2, object]. Такой порядок еще называется линеаризацией класса MultiDerived, а список правил, по которому мы находим такой порядок, называется Method Resolution Order (порядок разрешения методов).

MRO должен сохранять локальный порядок старшинства, а также обеспечивать монотонность. Он гарантирует, что класс всегда будет появляться до родителей. В случае нескольких родителей порядок будет таким же, как у кортежей в базовом классе.

MRO класса можно просмотреть в атрибуте __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:

# Как работает 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

# Вывод:
# [<class '__main__.M'>, <class '__main__.B'>,
#  <class '__main__.A'>, <class '__main__.X'>,
#  <class '__main__.Y'>, <class '__main__.Z'>,
#  <class 'object'>]
print(M.mro())

Вывод:

[<class '__main__.M'>, <class '__main__.B'>, <class '__main__.A'>, <class '__main__.X'>, <class '__main__.Y'>, <class '__main__.Z'>, <class 'object'>]

👉 Подробнее про порядок разрешения методов в Python.

codechick

СodeСhick.io - простой и эффективный способ изучения программирования.

2024 ©