【问题标题】:Why the base class doesn't work in this multiple inheritance?为什么基类在这种多重继承中不起作用?
【发布时间】:2018-07-13 13:39:42
【问题描述】:

我对解释以下代码的 MRO 和 C3 线性化算法感到困惑,请您帮帮我吗?

class A(object):
    def go(self):
        print("A")

class B(A):
    def go(self):
        super(B, self).go()
        print("B")

class C(A):
    def go(self):
        # super(C, self).go()
        print("C")

class D(B, C):
    def go(self):
        super(D, self).go()
        print("D")

d = D()
d.go()
pprint.pprint(D.__mro__)

The Result is:
C
B
D
(<class '__main__.D'>,
 <class '__main__.B'>,
 <class '__main__.C'>,
 <class '__main__.A'>,
 <class 'object'>)

另一个例子是:如果我在C类中取消注释super语句,在B类中注释super语句,结果将是“B D”,没有C和A。为什么?!!!!!! (我确实理解深度优先,从左到右的规则,但是……)

【问题讨论】:

  • 为什么把C的super call注释掉了? up变量/打印的目的是什么?
  • 还有不懂的地方请解释一下。鉴于您发布的代码,输出是我所期望的,因此您需要更清楚您期望的不同之处以及原因。
  • 我只是想很好地理解多重继承。所以我尝试了不同的条件来查看结果。

标签: python method-resolution-order


【解决方案1】:

super() 方法只是根据 MRO 找到下一个要调用的方法。

D.go() 调用B.go(),然后调用C.go(),它打印C 并返回到B.go(),它打印B,最后返回到D.go(),它打印D

如果您希望调用所有go() 方法,则必须取消注释C.go() 中的super() 调用。

您可以从 Guido 自己的blog 中找到有关 MRO 和 super() 的更多信息

【讨论】:

  • 谢谢。我确实阅读了您提到的博客,但仍然对某些情况感到有些困惑
【解决方案2】:

来自Guido's blog

MRO 的计算被正式记录为使用深度优先的从左到右的类遍历。如果在此搜索中重复了任何类,则将从 MRO 列表中删除除最后一个之外的所有类。

如果你有,例如:

class A: pass
class B(A): pass
class C(A): pass
class D(B, C): pass

MRO 不是采用简单的深度优先分辨率顺序 D, B, A, C, A,而是删除重复元素的最后一个实例以外的所有实例,因此您有 D, B, C, A。在您的情况下,您的班级 C 不会将其称为 super() (因为您已将其注释掉)。因此,除非我弄错了,否则 MRO 会将对 A 的调用推迟到 C 之后,但由于 C 不调用它的 super(),你永远不会看到 A.go() 被调用:

D.go() --> B.go() (--> A.go() removed by MRO) --> C.go() (x> A.go() not called)

【讨论】:

  • 谢谢你的回复,我明白了。但是,如果B 不调用它的super()C 调用它的super(),为什么结果是“B\n D\n”?为什么C.go() 从不打印?
  • 我相信,一旦你到达任何不叫它super()的东西,分辨率就结束了,你可以停止搜索其他方法。不过我可能是错的......
  • 我想也是。但是找不到官方的解释。非常感谢!
猜你喜欢
  • 1970-01-01
  • 2015-02-12
  • 2020-04-07
  • 1970-01-01
  • 1970-01-01
  • 2013-05-29
  • 2021-02-26
  • 1970-01-01
  • 2011-01-23
相关资源
最近更新 更多