python - Python 的 MRO、C3 线性化是否深度优先?根据经验,它没有

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

我正在阅读 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 构建图表,那么根据深度优先,它应该遵循以下内容:

enter image description here

路径应该是:

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 中它出现得更晚。

这是怎么回事?

最佳答案

and path should be:

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

F 不能出现在 D 之前 - 这将是矛盾的 - 参见类 D。

C3 线性化算法的工作方式,你必须先线性化 parent ,然后,只要不矛盾,你就可以线性化 child 。所以我一次线性化这些,从 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 

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

  1. 父级 MRO 保持一致
  2. 本地 MRO 保持一致
  3. 无周期性

算法,正如我所说的,是你从左到右尊重 parent ,但首先是深度,除非你会到达一个被 child 阻止的共享 parent (例如 F 被它的 child 阻止,D)在这种情况下你会寻找其他候选人(D然后,不矛盾,可以,然后你可以选择F和C的MRO的其余部分。)

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

直接线性化而不先线性化 parent

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

enter image description here

再次,

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

关于python - Python 的 MRO、C3 线性化是否深度优先?根据经验,它没有,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40478154/

相关文章:

python - Matplotlib:仅在可用时才使用 TeX

python - pip install -U setuptools 使 windows 10 失败

python - pandas:DTypeWarning,但我指定了 dtypes

python - 我如何使用字典来转换 python 中的数组?

php - 特殊图中的最重路径(PHP)

graph - Mathematica 8 中的多重图

python - MySQLdb 查询包含 NULL 到 Numpy 数组

python - 如何将数组合并为单个?

algorithm - 如何找到图形的直径?

python - 使用 Limits 获取索引名称 pandas dataframe python