Python多重继承调用父类方法的异常行为解析及需求实现方案
代码运行机制解析
先看这段代码的继承结构:C同时继承了A和B,Python会为每个类生成方法解析顺序(MRO),C的MRO是[C, A, B, object]——也就是说,当调用实例的方法时,会按这个顺序查找对应的方法实现。
再看C.foo里的两个super调用:
super(A, self).foo():super的第一个参数指定了查找的“起点”,它会在self(C实例)的MRO里找到A的下一个类,也就是B,所以这行实际调用的是B.foo(),会打印"B"。super(B, self).foo():MRO里B之后的类是object,而object没有定义foo方法,所以运行到这里会直接抛出AttributeError错误。
这就是原代码无法实现预期效果的核心原因。
实现预期行为的方案
要让调用c.foo()时依次打印"A"和"B",有两种简单可行的方式:
方式一:直接调用父类方法
跳过super,直接通过父类名调用方法并传入self参数:
class A: def foo(self): print("A") class B: def foo(self): print("B") class C(A, B): def foo(self): A.foo(self) # 直接调用A的foo方法 B.foo(self) # 直接调用B的foo方法 if __name__ == "__main__": c = C() c.foo()
方式二:结合super与显式调用
先用无参数的super()调用A的foo(super()默认以当前类C为起点,在MRO里找到下一个类A),再显式调用B的foo:
class A: def foo(self): print("A") class B: def foo(self): print("B") class C(A, B): def foo(self): super().foo() # 等价于super(C, self).foo(),调用A的foo B.foo(self) # 调用B的foo方法 if __name__ == "__main__": c = C() c.foo()
这两种方式都能实现预期效果,运行后会依次输出"A"和"B"。
内容的提问来源于stack exchange,提问作者George Ogden
相关产品推荐
相关产品推荐

