一个非常简单的钻石型继承案例:
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()
对于大多数目的而言,最简单的 例如,你可以想到搜索 从父级继承的属性 作为深度优先,从左到右, 不要在同一个班级中搜索两次 在哪里有重叠 层次结构。
因此,我希望我的例子按顺序解决:AB - > A - >根 - > B.但事实并非如此。使用ActiveState Python 3.1.2,输出为'B'而不是'Root'。
我错过了什么?
另外,我注意到ActiveState Python 2.6使用相同的代码打印“Root”。分辨率规则是否在2.6和3.1之间变化?
答案 0 :(得分:9)
Python 2.6打印Root,因为Root
是一个旧式类。如果B
继承自Root
(使其成为新式类),则应打印object
。
旧样式类不使用C3 MRO,而是使用旧的有缺陷的MRO,这正是引用文本所描述的内容。
B出现在Root之前的原因是因为B也从Root继承。
AB的继承图是:
AB - A - Root -- object
\ /
B
所以:
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]
在多重继承的情况下,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]
可以在http://www.python.org/download/releases/2.3/mro/中找到更多详细信息。