Все классы в Python 3 имеют общий базовый класс object
. Вы можете опустить класс из определения class
, но он будет там, если вы уже не наследуете его косвенно от object
. (В Python 2 вы должны явно наследовать от object
, чтобы даже использовать super()
, поскольку это функция класса нового стиля).
Вы изменили базовый класс B
с X
на object
, но X
также наследуется от object
. MRO был изменен с учетом этого. То же упрощение правил C3 (потомки идут раньше родителей, и порядок подклассов соблюдается) здесь все еще применяется. B
предшествует object
, как и X
, а A
и B
по-прежнему перечислены в том же порядке. Однако X
должен стоять перед B
, поскольку оба наследуются от object
, а подкласс A(X)
идет перед B
в KID
.
Обратите внимание, что нигде не сказано, что C3 сначала в ширину. Во всяком случае, это прежде всего глубина. См. Порядок разрешения методов Python 2.3 для получения подробное описание алгоритма и того, как он применяется к Python, но линеаризация любого класса является результатом объединения линеаризаций базовых классов и самих базовых классов:
L[KID] = KID + merge(L[A], L[B], (A, B))
где L[..]
- линеаризация C3 этого класса (их MRO).
Таким образом, линеаризация A
происходит перед B
при слиянии, заставляя C3 смотреть на иерархии в глубину, а не вширь. Слияние начинается с самого левого списка и берет любой элемент, который не появляется в хвостах других списков (то есть все, кроме первого элемента), затем берет следующий и т. Д.
В вашем первом примере L[A]
и L[B]
почти одинаковы (они оба оканчиваются на (X, object)
, что и их MRO, только первый элемент отличается), поэтому слияние выполняется просто; вы объединяете (A, X, object)
и (B, X, object)
, и их объединение дает вам только A
из первого списка, затем весь второй список, заканчивающийся (KID, A, B, X, object)
после добавления KID
:
L[KID] = KID + merge((A, X, object), (B, X, object), (A, B))
# ^ ^^^^^^
# \ & \ both removed as they appear in the next list
= KID + (A,) + (B, X, object)
= (KID, A, B, X, object)
Во втором примере L[A]
без изменений, но L[B]
теперь (B, object)
(отбрасывается X
), поэтому при слиянии предпочтительнее X
перед B
, поскольку (A, X, object)
идет первым при слиянии, а X
не отображается во втором списке. Таким образом
L[KID] = KID + merge((A, X, object), (B, object), (A, B))
# ^^^^^^
# \removed as it appears in the next list
= KID + (A, X) + (B, object)
= (KID, A, X, B, object)
person
Martijn Pieters
schedule
14.09.2016
object
), но это не является требованием C3. Наличие общего базового класса - очень веская причина для использования C3, поскольку он решает проблему с алмазом что подразумевает. - person Martijn Pieters   schedule 14.09.2016