MRO或C3线性化是否适用于深度优先?

时间:2016-11-08 02:50:58

标签: python python-3.x graph method-resolution-order

我正在阅读this article然后我发现了stackoverflow question但是在这个问题中,像Alex Martelli这样的程序员说它采用了深度优先的方法,所以现在我有很大的疑问。

示例:

class H():
    def m(self):
        print("H")

class G(H):
    def m(self):
        print("G")
        super().m()

class I(G):
    def m(self):
        print("I")
        super().m()


class F(H):
    def m(self):
        print("F")
        super().m()

class E(H):
    def m(self):
        print("E")
        super().m()

class D(F):
    def m(self):
        print("D")
        super().m()

class C(E, F, G):
    def m(self):
        print("C")
        super().m()

class B():
    def m(self):
        print("B")
        super().m()

class A(B, C, D):
    def m(self):
        print("A")
        super().m()

x = A()
x.m()

因此,如果我在MRO上建立图表基础,那么根据深度优先,它应该遵循:

enter image description here

和路径应该是:

A - >乙 - > C - > e - >的F - &GT克 - > d - > H

但如果你运行上面的代码,你会得到:

A
B
C
E
D
F
G
H

因为它遵循这条道路:

A - >乙 - > C - > e - > d - >的F - &GT克 - > H

现在我对节点“D”或类“D”的深度感到困惑,首先是它在早些时候出现,而在MRO中,它后来发生了什么?

1 个答案:

答案 0 :(得分:6)

  

和路径应该是:

     

A - >乙 - > C - > e - >的F - &GT克 - > d - > H

F不能在D之前出现 - 这将是一个矛盾 - 见D级。

C3线性化算法的工作方式,你必须线性化父母,然后,只要没有矛盾,你就可以线性化孩子。所以我从父母那里开始一次线性化这一个。大多数都是微不足道的,直到我们到达C然后A:

class PrettyType(type):
    def __repr__(self):
        return self.__name__

O = PrettyType('O', (object,), {})

class H(O): 'H, O, object'
# H's parent is object, assuming Python 3

class G(H): 'G, H, O, object'
# G's linearization is itself followed by its parent's linearization.

class I(G): 'I, G, H, O, object'
# I's linearization is I followed by G's

class F(H): 'F, H, O, object'

class E(H): 'E, H, O, object'

class D(F): 'D, F, H, O, object'

class C(E, F, G): 'C, E, F, G, H, O, object' 
# C's linearization is C followed by a consistent linearization of 
# its parents, left to right. 
# First C, then E - then you might be tempted to put H after E,
# but H must come after F and G (see class F and G)
# so we try F's linearization, noting that H comes after G,
# so we try G's linearization, H then consistently comes next, then object

class B(O): 'B, O, object'

A是:

class A(B, C, D): 'A, B, C, E, D, F, G, H, O, object'
# final complex case -      ^--^ can't go from E to F 
#                                D must come before F (see class D)
#                              ^--^ After D, can do F, 
#                                    then finish with C's MRO 
#                                    with no contradictions 

正如我将其解释的那样,3条准则是:

  1. 父母MRO保持一致
  2. 本地MRO保持一致
  3. 没有周期性
  4. 正如我所说的那样,算法是你从左到右尊重父母,但是除非你得到一个被孩子阻止的共同父母(例如F被其孩子D阻止),否则首先要深入了解父母,在这种情况下你会寻找其他候选人(D然后,不是一个矛盾,很好,那么你可以选择F和C的MRO的其余部分。)

    >>> A.mro()
    [A, B, C, E, D, F, G, H, O, <class 'object'>]
    

    直接线性化而不首先将父母线性化

    我们可以通过避免矛盾来完成线性化。

    enter image description here

    再次,

    • 从左到右
    • 深度优先 - 除非共享父级被阻止(必须能够回来)
    • 不允许有周期性关系