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构建一个图表,那么首先根据深度,它应该遵循以下步骤:
。
路径应该是:
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 |
号
这三个标准,正如我将要解释的那样:
我想说的算法是,你从左到右尊重父母,但首先要深入,除非你找到一个被孩子阻止的共享父母(例如,被孩子阻止的f,d),在这种情况下,你会寻找其他候选人(d,不是矛盾的,很好,然后你可以选择f和c的mro的剩余部分。)
1 2 | >>> A.mro() [A, B, C, E, D, F, G, H, O, <class 'object'>] |
直接线性化而不首先对父母进行线性化
我们可以通过线性化来避免矛盾。
。
再一次,
- 从左到右
- 深度优先-除非共享父级被阻止(必须能够返回)
- 不允许循环关系
小精灵