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
'''
唤醒过程由以下两个因素决定:
- 类的方法解析顺序
- 各方法中使用的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),那么在Leaf.__mro__中,B类将出现在A类前面,这会影响pong方法的唤醒顺序,而且left1.pong()将通过继承树唤醒B.pong,但是不唤醒A.poong和Root.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这样的类可以作为混入类使用。混入类意在与多重继承中的其他类结合在一起使用,提供额外的功能