使用super()访问第二个基类的方法

时间:2016-02-10 12:41:40

标签: python class oop python-3.x inheritance

请向我解释以下内容。如果我执行这个:

class Base1:
    def foo(self):
        print('in Base1.foo')

b1 = Base1()
b1.foo()


class Base2:
    def foo(self):
        print('in Base2.foo')

b2 = Base2()
b2.foo()

class Child1(Base1, Base2):
    def foo(self):
        super(Child1,self).foo()

c1 =  Child1()
c1.foo()

class Child2(Base1, Base2):
    def foo(self):
        super(Base1,self).foo()

c2 =  Child2()
c2.foo()

我明白了:

in Base1.foo
in Base2.foo
in Base1.foo
in Base2.foo

我理解输出的前三行。但为什么我必须将第一个基类的名称赋予super()才能获得第二个基类的方法?

1 个答案:

答案 0 :(得分:4)

您正在使用Method Resolution Order MRO 。根据一个名为C3 linearisation的系统,Python类继承层次结构是 linearised ,给定一个特定的顺序。

super()使用该顺序在该排序中查找 next 属性(包括方法)。给定当前实例和类,它将在订单中搜索给定类的属性过去。对于两个Child*类,MRO首先列出Child*类,然后是Base1Base2。在上一个示例中,您告诉super()Base1之后从下一课开始查看该MRO,因此只剩下Base2.foo()

您可以致电class.mro() method

向任何课程询问其MRO
>>> Child2.mro()
[<class '__main__.Child2'>, <class '__main__.Base1'>, <class '__main__.Base2'>, <class 'object'>]

super()也可以在外部方法中使用;然后,您可以轻松地看到当您为搜索选择不同的起点时会发生什么:

>>> super(Child2, Child2()).foo
<bound method Base1.foo of <__main__.Child2 object at 0x10f40ff98>>
>>> super(Base1, Child2()).foo
<bound method Base2.foo of <__main__.Child2 object at 0x10f40ffd0>>
>>> super(Base2, Child2()).foo
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'super' object has no attribute 'foo'