方法解析顺序MRO

时间:2019-04-15 15:45:24

标签: python method-resolution-order

为什么搜索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'>)

enter image description here

1 个答案:

答案 0 :(得分:1)

在您的特定示例中,搜索B后,我们无法立即考虑Y,因为它是A的子级。我们不能立即考虑Z,因为M继承自A ,而则继承自Z


Python使用C3方法解析顺序details here

C3分辨率命令很好地解决了钻石继承问题

在下面的示例中,我们有一个非常通用的类Object,它是BC的超类。如果__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