Python - 多重继承

class Root:
    def ping(self):
        print(f'{self},ping() in Root')

    def pong(self):
        print(f'{self}.pong in Root')

    def __repr__(self):
        cls_name = type(self).__class__
        return f'<instance of {cls_name}>'


class A(Root):
    def ping(self):
        print(f'{self},ping() in A')
        super().ping()

    def pong(self):
        print(f'{self}.pong in A')
        super().pong()

class B(Root):
    def ping(self):
        print(f'{self},ping() in B')
        super().ping()

    def pong(self):
        print(f'{self}.pong in B')



class Left(A,B):
    def ping(self):
        print(f'{self},ping() in Left')
        super().ping()

if __name__ == '__main__':
    left1 = Left()
    left1.ping()

'''
<instance of Left>.ping() in Left
<instance of Left>.ping() in A
<instance of Left>.ping() in B
<instance of Left>.ping() in Root
'''

唤醒过程由以下两个因素决定:

  • Leaf 类的方法解析顺序
  • 各方法中使用的super()

每个类都有名为__mro__ 的属性,它的值是一个元组,按照方法解析顺序列出各个超类,从当前类一直到object类。
Leaf 类的 __mro__ 属性如下所示:

(<class '__main__.Left'>, <class '__main__.A'>, <class '__main__.B'>, <class '__main__.Root'>, <class 'object'>)

if __name__ == '__main__':
    left1 = Left()
    left1.pong()
'''
<instance of Left>.pong in A
<instance of Left>.pong in B
'''

上列中,由于Leaf 类没有覆盖方法,因此调用left1.pong 唤醒的是Leaf.__mro__ 中下一个类(A类)实现的pong 方法. A.pong 方法调用了super().pong()。 方法解析顺序的下一个类是B,因此B.pong被唤醒。但是,因为B.pong 方法没有调用super().pong() ,所以唤醒过程到此结束

class Left(B,A):
    def ping(self):
        print(f'{self}.ping() in Left')
        super().ping()

if __name__ == '__main__':
    left1 = Left()
    left1.pong()
    print(Left.__mro__)
'''
<instance of Left>.pong in B
(<class '__main__.Left'>, <class '__main__.B'>, <class '__main__.A'>, <class '__main__.Root'>, <class 'object'>)
'''

该列中Leaf 类声明为Leaf(B,A), 那么在Lead.__mro__ 中,B类将出现在A类前面,这会影响pong方法 的唤醒顺序,而且left1.pong() 将通过继承树唤醒B.pong,但是不唤醒A.poong 和Rootf.pong ,因为B.pong 没有调用super()

调用super() 的方法叫做协作方法。利用协作方法可以实现协作多重继承。Python中多重继承涉及多个方法的协作。在B类中ping是协作方法,而pong则不是

class LeftUA(U,A):
    def ping(self):
        print(f'{self}.ping() in LeftUA')
        super().ping()

if __name__ == '__main__':
    left3 = LeftUA()
    left3.ping()
    print(LeftUA.__mro__)

'''
<instance of LeftUA>.ping() in LeftUA
<instance of LeftUA>.ping() in U
<instance of LeftUA>.ping() in A
<instance of LeftUA>.ping() in Root
(<class '__main__.LeftUA'>, <class '__main__.U'>, <class '__main__.A'>, <class '__main__.Root'>, <class 'object'>)
'''
class U():
    def ping(self):
        print(f'{self}.ping() in U')
        super().ping()

class LeftAU(A,U):
    def ping(self):
        print(f'{self}.ping() in LeftAU')
        super().ping()

if __name__ == '__main__':
    left2 = LeftAU()
    left2.ping()
    print(LeftAU.__mro__)
'''
<instance of LeftAU>.ping() in LeftAU
<instance of LeftAU>.ping() in A
<instance of LeftAU>.ping() in Root
(<class '__main__.LeftAU'>, <class '__main__.A'>, <class '__main__.Root'>, <class '__main__.U'>, <class 'object'>
'''

在真实的程序中,U 这样的类可以作为混入类使用。混入类意在与多重继承中的其他类结合在一起使用,提供额外的功能

posted @ 2023-06-04 11:45  chuangzhou  阅读(48)  评论(0编辑  收藏  举报