Python多继承下调用双父类run方法仅执行首个父类实现是Bug吗?
结论
该现象不属于Python的Bug,是Python类方法查找机制的正常表现。
原因分析
你调用CarChild1.run(self)和CarChild2.run(self)时传入的self始终是CarChild3的实例,而run方法内部调用self._print_name时,Python会按照CarChild3的方法解析顺序(MRO)查找对应方法。
由于CarChild3的继承顺序为(CarChild1, CarChild2),且自身没有实现_print_name方法,MRO中排在前面的CarChild1的_print_name会被优先匹配,因此两次调用最终都执行了CarChild1的打印逻辑,才会输出两次CarChild1。
解决方案
以下三种方案都可以实现你预期的输出效果:
方案1:父类run方法显式绑定自身的打印方法
无需修改子类,直接调整父类run方法的实现,固定调用当前类的打印逻辑,不通过self动态查找:
class CarChild1: def run(self): CarChild1._print_name(self) def _print_name(self): print('CarChild1') class CarChild2: def run(self): CarChild2._print_name(self) def _print_name(self): print('CarChild2') class CarChild3(CarChild1, CarChild2): def run(self): CarChild1.run(self) CarChild2.run(self)
方案2:子类直接调用两个父类的打印方法
如果父类代码不可修改,可以直接调整子类run方法,跳过父类run的动态查找逻辑:
class CarChild3(CarChild1, CarChild2): def run(self): CarChild1._print_name(self) CarChild2._print_name(self)
方案3:使用双下划线私有方法避免覆盖
Python中双下划线开头的方法会被自动做名称修饰,不会被子类的同名方法覆盖,是官方推荐的类私有方法实现方式:
class CarChild1: def run(self): self.__print_name() def __print_name(self): print('CarChild1') class CarChild2: def run(self): self.__print_name() def __print_name(self): print('CarChild2') class CarChild3(CarChild1, CarChild2): def run(self): CarChild1.run(self) CarChild2.run(self)
三种方案运行后都会输出预期结果:
CarChild1 CarChild2
内容的提问来源于stack exchange,提问作者InfoLearner
相关产品推荐
相关产品推荐

