Классы в Python составляются динамически - это включает наследование.
Вывод C:b
не подразумевает, что B
магически наследуется от C
.Если вы создаете экземпляр B
или C
, никто не знает о другом.
>>> B('root')
B:root
A:b
Однако, D
знает о B
и C
:
class D(B,C):
...
Существует множество технических моментов доступно на этом.Однако в основном это состоит из двух частей:
- Прямые базовые классы разрешаются в порядке их появления.
- Рекурсивные базовые классы разрешены не для дублирования.
- Базовый класс как
B
, так и C
должен следовать за обоими.
Для класса D
это означает, что базовые классы разрешаюткак B->C->A
!C
проскользнул между B
и A
- но только для класса D
, а не для класса B
.
Обратите внимание, что на самом деле другой задействованный класс: по умолчанию все классы наследуются от object
.
>>> D.__mro__
(__main__.D, __main__.B, __main__.C, __main__.A, object)
Вы уже написали A
, зная, что для его параметров нет базы.Однако ни B
, ни C
не могут принять это.Они оба рассчитывают получить от объекта A
.Подклассы подразумевают, что оба B
и C
являются действительными A
-объектами, хотя!
Это действительный для обоих B
и C
предшествует B
и C
, поскольку оба являются подклассами A
.B->C->A->object
не нарушает того, что B
ожидает, что его суперкласс будет иметь тип A
.
Со всеми другими комбинациями одна заканчивается с C
предшествующим ничему (недействительным) или object
предшествующимчто-то (неверно).Это исключает разрешение по глубине B->A->object->C
и дублирует B->A->object->C->A->object
.
Этот порядок разрешения методов полезен для включения mixins : классов, которые полагаются на другие классы, чтобы определить, какметоды разрешены.
Есть хороший пример того, как регистратор для доступа к словарю может принимать как dict
, так и OrderedDict
.
# basic Logger working on ``dict``
class LoggingDict(dict):
def __setitem__(self, key, value):
logging.info('Settingto %r' % (key, value))
super().__setitem__(key, value)
# mixin of different ``dict`` subclass
class LoggingOD(LoggingDict, collections.OrderedDict):
pass