关于python:MRO或C3线性化是否可以在深度优先工作?

Is MRO or C3 linearization works on Depth-first?

我读了这篇文章,然后我发现了stackoverflow问题,但是在这个问题中,一些程序员如alex martelli说它使用深度优先的方法,所以现在我有很大的疑问。

例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
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——>B——>C——>E——>F——>G——>D——>H

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

1
2
3
4
5
6
7
8
A
B
C
E
D
F
G
H

因为它遵循这条路径:

A——>B——>C——>E——>D——>F——>G——>H

现在我对节点"D"或类"D"有了一些困惑,首先是它出现在更早的时候,然后在MRO中出现在更晚的时候,这里发生了什么?


and path should be:

A-->B-->C-->E-->F-->G-->D-->H

F不能排在D之前——这是一个矛盾——见D类。

c3线性化算法的工作方式是,必须对父对象进行线性化,然后,只要没有矛盾,就可以对子对象进行线性化。所以我一次线性化这些,从父母开始。大多数都是琐碎的,直到我们到达C,然后到达A:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
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是:

1
2
3
4
5
6
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

这三个标准,正如我将要解释的那样:

  • 父母的MRO是始终如一的
  • 当地的MRO保持一致
  • 无周期性
  • 我想说的算法是,你从左到右尊重父母,但首先要深入,除非你找到一个被孩子阻止的共享父母(例如,被孩子阻止的f,d),在这种情况下,你会寻找其他候选人(d,不是矛盾的,很好,然后你可以选择f和c的mro的剩余部分。)

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

    直接线性化而不首先对父母进行线性化

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

    enter image description here

    再一次,

    • 从左到右
    • 深度优先-除非共享父级被阻止(必须能够返回)
    • 不允许循环关系
    • 小精灵