在多重继承中调用超类方法

时间:2017-07-29 14:45:04

标签: python python-3.x multiple-inheritance super

我有以下代码:

class A:
    pass

class B(A):
    def foo(self, a):
        if a:
            return 'B'
        return super(B, self).foo(a)

class C:
    def foo(self, a):
        return 'C'

class D(B, C):
    def foo(self, a):
        return super().foo(a)

d = D()
print(d.foo(0))

当我根据MRO调用d.foo(0)时,它首先调用foo类的B方法,并在其中,如果条件错误,它将返回super(B, self).foo(0)但是class A没有foo方法,我期待这个错误:

AttributeError: 'super' object has no attribute 'foo'

但它会从班级'C'返回C。为什么呢?

1 个答案:

答案 0 :(得分:1)

super()在MRO中搜索具有该属性的 next class ; <{1}}未实现它并不重要,因为仍然会考虑A

对于C,MRO为DDBA

C

因此>>> D.__mro__ (<class '__main__.D'>, <class '__main__.B'>, <class '__main__.A'>, <class '__main__.C'>, <class 'object'>) 中的super().foo会找到D,而B.foo会跳过B.foo,并找到A;你可以从交互式翻译中自己测试一下:

C.foo

这是属性搜索算法的Python实现:

>>> super(D, d).foo
<bound method B.foo of <__main__.D object at 0x1079edb38>>
>>> super(B, d).foo
<bound method C.foo of <__main__.D object at 0x1079edb38>>

其中def find_attribute(type_, obj, name): starttype = type(obj) mro = iter(starttype.__mro__) # skip past the start type in the MRO for tp in mro: if tp == type_: break # Search for the attribute on the remainder of the MRO for tp in mro: attrs = vars(tp) if name in attrs: res = attrs[name] # if it is a descriptor object, bind it descr = getattr(type(res), '__get__', None) if descr is not None: res = descr( res, None if obj is starttype else obj, starttype) return res type_的第一个参数(方法定义的类),super()是实例(因此obj)和{{ 1}}是您要查找的属性。