Python 3.1:C3方法解析顺序

max*_*max 4 multiple-inheritance python-3.x

一个非常简单的钻石型继承案例:

class Root:
    def f(self):
        print('Root')

class A(Root): pass

class B(Root):
    def f(self):
        print('B')

class AB(A, B): pass

AB().f()
Run Code Online (Sandbox Code Playgroud)

根据Python 3.1.2文档:

在大多数情况下,在最简单的情况下,您可以将从父类继承的属性的搜索视为深度优先,从左到右,而不是在层次结构中存在重叠的同一类中搜索两次.

因此,我希望我的例子按顺序解决:AB - > A - > Root - > B.但事实并非如此.使用ActiveState Python 3.1.2,输出为'B'而不是'Root'.

我错过了什么?

另外,我注意到ActiveState Python 2.6使用相同的代码打印"Root".决议规则是否在2.6和3.1之间变化?

ken*_*ytm 9

Python 2.6打印Root因为Root是一个旧式的类.B如果Root继承object(使其成为新式类),它应该打印.

旧样式类不使用C3 MRO,而是使用旧的有缺陷的MRO,这正是您引用的文本描述的内容.


B出现在Root之前的原因是因为B也从Root继承.

AB的继承图是:

 AB - A - Root -- object
    \   /
      B
Run Code Online (Sandbox Code Playgroud)

所以:

mro(object) = [object]
mro(Root)   = [Root] + mro(object)   # mro of single-inherited class is simple...
            = [Root, object]
mro(A)      = [A, Root, object]
mro(B)      = [B, Root, object]
Run Code Online (Sandbox Code Playgroud)

在多重继承的情况下,MRO是通过从左到右获取超类的MRO中的元素来计算的,这些元素不会出现在中间.在示例中更好地解释:

mro(AB) = [AB] + merge(mro(A), mro(B))
        = [AB] + merge([A, Root, object], [B, Root, object])   
        = [AB] + [A] + merge([Root, object], [B, Root, object])
           # A appears at head, pop it.
        = [AB] + [A] + [B] + merge([Root, object], [Root, object])
           # cannot pop Root because Root is not at head of [B, Root, object]
           # pop B instead.
        = [AB] + [A] + [B] + [Root] + merge([object], [object])
           # now we can pop Root because it only appears at the head position
        = [AB] + [A] + [B] + [Root] + [object]
        = [AB, A, B, Root, object] 
Run Code Online (Sandbox Code Playgroud)

更多细节可以在http://www.python.org/download/releases/2.3/mro/找到.