Calling super class method in multiple inheritance

时光总嘲笑我的痴心妄想 提交于 2019-12-12 04:58:08

问题


I have the following code:

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

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'

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


回答1:


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.

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

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

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

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.



来源:https://stackoverflow.com/questions/45390553/calling-super-class-method-in-multiple-inheritance

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!