在多重继承的情况下,super方法如何在python中工作?

Kul*_*shi 8 python oop inheritance multiple-inheritance method-resolution-order

超级方法如何在python中实际运行?

在给定的代码中:

class A(object):
    def test(self):
        return 'A'


class B(A):
    def test(self):
        return 'B->'+super(B, self).test()


class C(A):
    def test(self):
        return 'C'


class D(B,C):
    pass


print B().test()    # B->A
print D().test()    # B->C  ????

# MRO of classes are as
print 'mro of A', A.__mro__   # [A,object]
print 'mro of B', B.__mro__   # [B,A,object]
print 'mro of C', C.__mro__   # [C,A,object]
print 'mro of D', D.__mro__   # [D,B,C,A,object]
Run Code Online (Sandbox Code Playgroud)

test在D上调用时,它输出B->C而不是B->A(我期待的).

B中的超级内容如何引用C的实例?

Kul*_*shi 1

在常见情况下, super() 采用两个参数:一个类和该类的实例。(1) 实例对象(自身)决定将使用哪个MRO来解析任何属性。(2) 提供的类确定该 MRO 的子集,因为 super() 仅使用 MRO 中出现在提供的类之后的那些条目。

因此,在上述情况下,当从 D 对象的实例调用 B 内部的 super 时,self 引用 D 对象(即实例对象),并且 D(即实例对象)的 mro 是 [D,B,C,A],因此根据 (2 )仅使用 MRO 中 B 之后出现的那些条目。即[C,A]

因此,推荐的用法是提供使用 super() 作为第一个参数、标准 self 作为第二个参数的类。生成的对象将保留 self 的实例命名空间字典,但它仅检索在 MRO 中晚于提供的类找到的类上定义的属性。

因此,如果我们将 B 重新定义为

class B(A):
    def test(self):
        return 'B->'+super(C, self).test()
Run Code Online (Sandbox Code Playgroud)

然后调用 D().test() 将输出 ==> 'B->A' 解释: from (1) 上述 MRO of self == [D,B,C,A,object] from (2) 以上仅那些将使用在提供的类(即 C)之后发生的 MRO 条目,因此 super 将调用 A 的测试方法。