python3 super()多重继承笔记

python内置的super()不只是简单的调用父类的方法,其实是根据mro(方法解析顺序)来进行调用的。当只是使用简单的继承的时候,根据mro的顺序,super()调用的是父类的方法,而当使用多重继承的时候,super()的调用顺序则完全不同。

class BaseClass:
    num_base_calls = 0

    def call_me(self):
        print('Calling method on Base Class')
        self.num_base_calls += 1


class LeftSubclass(BaseClass):
    num_left_calls = 0
    def call_me(self):
        super().call_me()
        print('Calling method on Left SubClass')
        self.num_left_calls += 1

class RightSubclass(BaseClass):
    num_right_calls = 0
    def call_me(self):
        super().call_me()
        print('Calling method on Right Subclass')
        self.num_right_calls += 1

class Subclass(LeftSubclass,RightSubclass):
    num_sub_calls = 0
    def call_me(self):
        super().call_me()
        print('Calling method on Subclass')
        self.num_sub_calls +=1

if __name__ == '__main__':
    s = Subclass()
    s.call_me()
    print(Subclass.mro())

最终结果为

Calling method on Base Class
Calling method on Right Subclass
Calling method on Left SubClass
Calling method on Subclass
[<class '__main__.Subclass'>, <class '__main__.LeftSubclass'>, <class '__main__.RightSubclass'>, <class '__main__.BaseClass'>, <class 'object'>]

可以看到,mro为Subclass->LeftSubclass->RightSubclass->BaseClass->object。(所有的对象都继承自object)
首先,Subclass的call_me方法调用了super().call_me(),其实就是引用了LeftSubclass.call_me()方法。然后LeftSubclass.call_me()调用了super().call_me(),但是这时的super()引用了RightSubclass.call_me()。要特别注意:super调用并不是调用LeftSubclass的超类(就是BaseClass)的方法,它是调用RightSubclass,虽然它不是LeftSubclass的父类!这就是根据mro得到的下一个方法,而不是父类方法。RigthSubclass然后调用BaseClass,并且通过super调用保证了在类的层次结构中每一个方法都被执行一次。

super流程图

最后:不要一说到 super 就想到父类!super 指的是 MRO 中的下一个类!

以上源码及内容摘抄自《Python3面向对象编程》

发表评论

电子邮件地址不会被公开。 必填项已用*标注