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

赛义德

我有以下代码:

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))

当我d.foo(0)基于 MRO 调用时,它首先调用foo方法B并在其中调用,如果条件错误,它将返回super(B, self).foo(0)但类A没有 foo 方法,我预计会出现此错误:

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

但它'C'从 class返回C为什么?

马丁·彼得斯

super()在 MRO 中搜索具有该属性下一个类A没有实现它并不重要,C仍然被认为是。

对于D,MRO 是D, B, A, C

>>> D.__mro__
(<class '__main__.D'>, <class '__main__.B'>, <class '__main__.A'>, <class '__main__.C'>, <class 'object'>)

所以super().fooD会发现B.foo,距离B.fooA被跳过,C.foo被发现; 您可以从交互式解释器中自行测试:

>>> 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>>

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

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

wheretype_super()(定义方法的类)的第一个参数obj是实例(所以type(d)在这里),name是你正在寻找的属性。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章