首页 > 解决方案 > Python MRO - 在多重继承中使用 super

问题描述

我有这段代码,其中使用了超级继承和多重继承。上课的结果是:

go A go!
go C go!
go B go!
go D go!

虽然我期望:

go A go!
go B go!
go D go!

根据我的理解:D因为MRO调用B类,因为go是在B中实现的。B类调用其父A的super。A被执行,没关系。然后我希望 B 继续执行,所以这意味着 B 被执行,最后 D 被执行。但这当然是不正确的。为什么它进入C,因为go方法的定义在B中找到,然后它不应该再在C中搜索。这就是MRO的工作原理。它在头等舱中找到,不应再搜索。完全糊涂了:(

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

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

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

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

a = A()
b = B()
c = C()
d = D()

d.go()

标签: pythonpython-3.xsupermethod-resolution-order

解决方案


Raymond Hettinger(核心 python 开发人员)在PyCon 上提供了一段出色的视频。

主要的收获是超级不叫你的父母,它叫你后代的祖先。因此,无论何时调用super,它都会返回到您实际调用该方法的实例,并在 MRO 中查找下一个类型(即使具有多重继承也是保证顺序,为什么class D(B,C)与 不同class D(C, B))。

在您的情况下,D 的 MRO 是 (D,B,C,A)。当D.go调用 super 时,它调用B.go. 当调用 super 时,它仍在使用 D 的 MRO,因此它移动到下一种类型,在您的情况下,C 又调用 A。最终结果是您的打印语句在 D 的 MRO 中执行反转。

如果您无法观看 youtube,这里还有一个 RH 的博客,其中也涵盖了相同的主题。


推荐阅读