为什么搜索B之后,搜索Y或z却不深入,而是搜索A?
Y是A的父级,如果应该先搜索A,而Y是B的父级,那么它应该先搜索Y,为什么这不会引发MRO错误?
有人可以解释此查询的工作原理吗?
class X(object):pass
class Y(object): pass
class Z(object): pass
class A(X,Y): pass
class B(Y,Z):pass
class M(B,A,Z):pass
print M.__mro__
给予
(<class '__main__.M'>, <class '__main__.B'>, <class '__main__.A'>, <class '__main__.X'>, <class '__main__.Y'>, <class '__main__.Z'>, <type 'object'>)
答案 0 :(得分:1)
在您的特定示例中,搜索B
后,我们无法立即考虑Y
,因为它是A
的子级。我们不能立即考虑Z
,因为M
继承自A
,而则继承自Z
。
Python使用C3方法解析顺序details here。
C3分辨率命令很好地解决了钻石继承问题
在下面的示例中,我们有一个非常通用的类Object
,它是B
和C
的超类。如果__repr__
和Object
都没有实现,我们只希望考虑B
中的方法实现(例如C
之类的东西)。
Object
/ \
B C
\ /
A
换句话说,考虑了A
的父类的传递闭包中的每个可能的父类,但是这些类是根据从基类开始的“最新”路径进行排序的到有问题的班级。
object
有两条路径:
A -> B -> Object
A -> C -> Object
“最新”路径为A -> C -> Object
,因为A -> B -> Object
在左偏深度优先搜索中会更早。
C3线性化满足两个关键不变式:
X
继承自Y
,则在X
之前检查Y
。Z
继承自U
,然后依次V
,则在U
之前检查V
。实际上C3
的线性化保证了这两个属性均成立。
可能会构造无法线性化的层次结构,在这种情况下,您会在类定义时遇到异常。
运行inherit.py
class E: pass
class F: pass
class A(E, F): pass
class B(F, E): pass
class Z(A, B): pass
产生以下错误。
Traceback (most recent call last):
File "inherit.py", line 5, in <module>
class Z(A, B): pass
TypeError: Cannot create a consistent method resolution
order (MRO) for bases E, F