我正在阅读Python Multiple Inheritance (on Programiz),然后发现了这个StackOverflow问题Method Resolution Order (MRO) in new-style classes?,但是在这个问题中,像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构建图形,则根据深度优先,应该遵循以下规则:
python - Python的MRO,C3线性化是否深度优先?根据经验,它不是-LMLPHP
路径应为:
A-> B-> C-> E-> F-> G-> D-> H
但是,如果您运行以上代码,则会得到:
A
B
C
E
D
F
G
H
因为它遵循以下路径:
A-> B-> C-> E-> D-> F-> G-> H
现在,我对节点“D”或类“D”的深度感到困惑,因为它先出现在较早的位置,而在MRO中则出现在较晚的时间。
这里发生了什么?

最佳答案


F不能在D之前出现-这将是一个矛盾-参见D类。
C3线性化算法的工作方式,必须线性化父级,然后,只要没有矛盾,就可以线性化子级。因此,从 parent 开始,我一次将这些线性化。直到我们到达C然后到达A为止,大多数都是微不足道的。

class PrettyType(type):
    """make the repr of the classes look nice when finally listed"""
    def __repr__(self):
        return self.__name__

# subclasses of O will also have the metaclass:
class O(metaclass=PrettyType): 'O, object'

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

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
我将其解释为以下三个标准:
  • parent MRO保持一致
  • 本地MRO保持一致
  • 没有周期性

  • 就像我要说的那样,算法是尊重 parent 从左到右,但要先深入,除非您遇到被 child 阻止的共享 parent (例如,被 child 阻止的F,D),在这种情况下,您看起来对于其他应聘者(D可以作为一个很好的选择,那么您可以选择F以及C的MRO的其余部分。)
    >>> A.mro()
    [A, B, C, E, D, F, G, H, O, <class 'object'>]
    
    直接线性化,无需先线性化父级
    我们可以通过避免矛盾来完成线性化。
    python - Python的MRO,C3线性化是否深度优先?根据经验,它不是-LMLPHP
    再次,
  • 从左到右
  • 深度优先-除非共享父级被阻止(必须能够回来)
  • 不允许周期性关系
  • 关于python - Python的MRO,C3线性化是否深度优先?根据经验,它不是,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/40478154/

    10-08 22:40