Python多继承中super关键字使用问题:为何输出不符合预期?
问题原因及解决方法
为什么会出现这个问题?
1. 用户名被覆盖成22的原因
Python多继承遵循方法解析顺序(MRO),类C的MRO顺序是[C, A, B, object]。你两次调用super(C, self).__init__()时,都会按照这个顺序找到第一个存在__init__方法的父类——也就是A:
- 第一次调用:用
userName='Tom'调用A.__init__,把self.userName设为Tom。 - 第二次调用:用
userAge=22调用A.__init__,直接覆盖了self.userName的值,变成22。
2. 两次showInfo都输出用户名的原因
同样遵循MRO规则,super(C, self).showInfo()每次都会从MRO中C的下一个类开始找,第一个有showInfo方法的是A,所以两次调用都是执行A.showInfo(),自然都输出用户名。
正确实现方式
要分别调用A和B的方法,有两种可行的写法:
方式1:直接指定父类调用
不依赖super,直接用父类名称调用方法并传入self:
class A: def __init__(self, userName=''): self.userName = userName def showInfo(self): print(f'User Name:{self.userName}') class B: def __init__(self, userAge=0): self.userAge = userAge def showInfo(self): print(f'User Age:{self.userAge}') class C(A, B): def __init__(self, userName='', userAge=0, userAddress=''): A.__init__(self, userName) # 直接调用A的构造方法 B.__init__(self, userAge) # 直接调用B的构造方法 self.userAddress = userAddress def showInfo(self): print('====User Data====') A.showInfo(self) # 调用A的showInfo B.showInfo(self) # 调用B的showInfo print(f'User Address:{self.userAddress}') tom = C('Tom', 22, 'shanghai') tom.showInfo()
方式2:通过super指定查找起点
如果想继续使用super,可以通过修改super的第二个参数,改变MRO的查找起点:
class C(A, B): def __init__(self, userName='', userAge=0, userAddress=''): super().__init__(userName) # 从C之后找,调用A的__init__ super(A, self).__init__(userAge) # 从A之后找,调用B的__init__ self.userAddress = userAddress def showInfo(self): print('====User Data====') super().showInfo() # 调用A的showInfo super(A, self).showInfo() # 从A之后找,调用B的showInfo print(f'User Address:{self.userAddress}')
运行上述任意一种代码,都会得到你期望的输出:
====User Data==== User Name:Tom User Age:22 User Address:shanghai
内容的提问来源于stack exchange,提问作者chenqiandaxianren
相关产品推荐
相关产品推荐

