【问题标题】:why MRO is reverse in python in below code?为什么 MRO 在下面的代码中在 python 中是反向的?
【发布时间】:2017-12-30 03:33:14
【问题描述】:
class Z():
    def func():
        print ("I'm in Z")
class A(Z):
    def func():
        print ("I'm in A")
class B(Z):
    def func():
        print ("I'm in B")

class C(A,B):
    pass
    #def func():
     #   print ("I'm in C")

ob1 = C

print ("Calling function func ")
ob1.func()

输出是:

Calling function func
I'm in A

但是根据How does Python's super() work with multiple inheritance?

顺序应该是“深度优先从左到右遍历”+“删除重复期望最后一个”

正如 /visionscaper(用户:889617)所解释的,

为什么会有这种差异?

【问题讨论】:

  • 它的深度从左到右。作为 C 的父母,A 离开了 B。是什么绊倒了你?
  • 从C开始,深度优先从左到右遍历的下一个基类是C的最左边基类:A。你期待什么?
  • 此处的查找顺序为 A、Z、B(A、Z 从 B 层次结构中删除为重复项。)
  • 我将继续投票结束,因为不清楚。
  • @MadPhysicist:您的订单不正确。在 MRO 中,B 必须出现在 Z 之前。

标签: python method-resolution-order


【解决方案1】:

继承层次结构C的深度优先从左到右遍历会给你:[C, A, Z, B, Z]。由于 Python 不允许重复,因此删除了第一个 Z,最终得到 [C, A, B, Z]。因此,当您调用C.func() 时,您会从A 获得实现。 A.func 中没有 super 调用,所以到此结束。

您可以通过调用其mro 方法来获取任何类的完整 MRO:

>>> C.mro()
[__main__.C, __main__.A, __main__.B, __main__.Z, object]

the answer I think you were referring to 中,每个__init__ 方法使用super 调用MRO 中的下一个方法。但是由于他们每个人都在打印自己的消息之前进行了super 调用,因此打印行的顺序最终与调用函数的顺序相反。您可以通过以下方式使其以与 MRO 相同的顺序工作将print 行与超级调用交换,以便print 调用首先发生。

【讨论】:

  • 嗨,Blckknght,感谢您消除疑虑。实际上,当我在上面的示例中使用超级功能时,我感到很困惑。你提到的线程是正确的,“我认为你所指的答案”
  • 也感谢其他人,他们试图消除我的疑虑。
【解决方案2】:

在谈到遍历时,它首先搜索深度,从左到右,直到找到它。它调用它找到的第一个。在你的情况下:

  1. 它在C 中搜索func - 没有找到。向左走。
  2. 它在A 中搜索func - 找到它。完毕。打印I'm in A

如果A 没有覆盖func,这很重要。在这种情况下:

  1. 它在C 中搜索func - 没有找到。向左走。
  2. 它在A 中搜索func - 没有找到。往下走,不对。
  3. 它在Z 中搜索func - 在那里找到它。打印I'm in Z

【讨论】:

  • 也可以完成:直接跳到 B,跳过 A、Z 作为重复项。检查实例字典。引发属性错误。
  • 你的第二种情况是完全错误的。如果A 没有实现func,那么B 的版本将被调用。 C 的 MRO 是 C, A, B, ZZ 在任何 MRO 中都不会出现在 B 之前,因为它是 B 的父级。
  • 啊,是的,我明白了,你是对的。这就是我不测试我写的东西所得到的。
猜你喜欢
  • 1970-01-01
  • 2018-12-30
  • 1970-01-01
  • 2011-02-27
  • 1970-01-01
  • 2019-06-24
  • 1970-01-01
  • 1970-01-01
  • 2020-03-12
相关资源
最近更新 更多