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



超级方法在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]

当在 D 上调用 test 时,它会输出B->C而不是B->A(这是我所期望的)。

B 内部的超级如何指代 C 的实例?

从文档中:

super(type[, object-or-type]): 返回将方法调用委托给父类或同级类的代理对象

强调我的。

MRO(如您打印出的)确定方法解析顺序,在本例中为 (D, B, C, A, 对象)。因此,super(B, self)D 中调用时返回一个代理对象,该对象将根据 MRO 将方法委托给其同级C

这实际上可用于扩展继承层次结构中的行为,而无需修改现有类。请注意,B实际上并不知道其test()方法将被调度到哪个类 - 它只是使用间接super()调用。只需创建一个按所需顺序混合多个基类的新类,即可在 MRO 中插入不同的类。

例如,假设原始层次结构仅包含类 ABD 。假设稍后,您需要使用日志记录来检测B的所有方法调用。与其修改B,不如简单地创建一个新的类C,该类执行日志记录并D继承C,从而将其插入 MRO 紧跟在 B 之后。

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

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

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

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

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

然后调用 D().test() 将输出 ==> 'B->A'解释:从 (1) 以上自我 MRO == [D,B,C,A,对象]从上面的 (2) 中,只会使用在提供的类(即 C)之后发生的 MRO 条目因此超级将调用 A 的测试方法。

相关内容

  • 没有找到相关文章

最新更新