Множественное наследование в 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'>]