Python多继承中方法调用顺序异常问题咨询
多继承中父类方法调用的MRO解析问题
问题重现
以下代码定义了继承A和B的子类USA,A和B均包含change_to_4方法。创建USA实例时,B的__init__方法中调用self.change_to_4(),实际执行的是A类的实现,导致输出与预期不符。
代码
class A: def __init__(self) -> None: self.a = 1 super().__init__() def change_to_4(self): self.x = 4 class B: def __init__(self) -> None: self.b = 2 self.change_to_4() super().__init__() def change_to_4(self): self.b = 4 class USA(A, B): def __init__(self) -> None: super().__init__() print(f"A vars = {vars(A())}") print(f"B vars = {vars(B())}") print(f"USA vars = {vars(USA())}") print(f"USA mro -> {USA.__mro__}")
预期输出
A vars = {'a': 1} B vars = {'b': 4} USA vars = {'a': 1, 'b': 4} USA mro -> (<class '__main__.USA'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>)
实际输出
A vars = {'a': 1} B vars = {'b': 4} USA vars = {'a': 1, 'b': 2, 'x': 4} USA mro -> (<class '__main__.USA'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>)
原因解析
问题核心在于Python的方法解析顺序(MRO)和实例方法的查找规则:
USA类的MRO顺序为USA → A → B → object,从输出的USA.__mro__可直接确认。- 当
self.change_to_4()被调用时,self是USA类的实例,方法查找严格遵循MRO顺序:USA实例初始化时,先执行A.__init__,其中的super().__init__()会根据MRO找到下一个类B,进而执行B.__init__。- 在
B.__init__中,调用self.change_to_4()时,Python会从MRO的第一个类开始查找change_to_4方法——A类的该方法排在B类之前,因此直接执行A.change_to_4,给实例添加了x=4,而B自身的change_to_4从未被调用,b的值停留在初始的2。
解决方案
如果希望在B.__init__中调用自身的change_to_4方法,最直接的方式是通过类名明确调用,绕开MRO的自动查找:
修改B类的代码如下:
class B: def __init__(self) -> None: self.b = 2 B.change_to_4(self) # 明确指定调用B类的方法 super().__init__() def change_to_4(self): self.b = 4
修改后执行代码,输出将与预期一致:
A vars = {'a': 1} B vars = {'b': 4} USA vars = {'a': 1, 'b': 4} USA mro -> (<class '__main__.USA'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>)
内容的提问来源于stack exchange,提问作者Ali Rashidi
相关产品推荐
相关产品推荐

