在多重继承中调用超类方法 [英] Calling super class method in multiple inheritance

查看:110
本文介绍了在多重继承中调用超类方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下代码:

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)时,它首先调用B类的foo方法,在其中,如果条件错误,它将返回super(B, self).foo(0),但类A没有foo方法而且我期望这个错误:

When I call d.foo(0) based on MRO it first calls the foo method of B class and inside that, if the condition is wrong and it will return super(B, self).foo(0) but class A has no foo method and I expect this error:

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

,但它从类C返回'C'.为什么?

but it returns 'C' from class C. Why?

推荐答案

super()在MRO中搜索具有该属性的下一类A不实现它并不重要,因为仍在考虑C.

super() searches the MRO for the next class that has the attribute; that A doesn't implement it doesn't matter as C is still considered.

对于D,MRO为DBAC:

For D, the MRO is D, B, A, C:

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

因此D中的super().foo将找到B.foo,并且从B.foo中跳过A并找到了C.foo;您可以从交互式解释器中对此进行测试:

so super().foo in D will find B.foo, and from B.foo, A is skipped and C.foo is found; you can test this yourself from the interactive interpreter:

>>> 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实现的样子:

This is what a Python implementation of the attribute search algorithm would look like:

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是实例(此处为type(d)),而name是您要查找的属性

where type_ is the first argument to super() (the class the method is defined on), obj is the instance (so type(d) here), and name is the attribute you are looking for.

这篇关于在多重继承中调用超类方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆