Python中子类未调用super()时代码不符合预期的原因探究
示例代码
为理解Python的super()机制,编写如下代码:
class Base(): def func(self): print("Base") class A(Base): def func(self): print("A runs func") super().func() print("A func done") class B(Base): def func(self): print("B runs func") super().func() print("B func done") class C(A, B): def func(self): print("C runs func") super().func() print("C func done") c = C() c.func() # 获取MRO print(c.__class__.__mro__)
不同场景下的输出
场景1:A、B均保留super()调用
输出符合方法解析顺序(MRO):
C runs func
A runs func
B runs func
Base
B func done
A func done
C func done
(<class 'main.C'>, <class 'main.A'>, <class 'main.B'>, <class 'main.Base'>, <class 'object'>)
场景2:注释A类中的super()调用
输出为:
C runs func
A runs func
A func done
C func done
场景3:仅注释B类中的super()调用
输出为:
C runs func
A runs func
B runs func
B func done
A func done
C func done
场景4:同时注释A、B类中的super()调用
输出效果与场景2一致:
C runs func
A runs func
A func done
C func done
疑问与解答
疑问:Python是否按MRO追踪执行,无super()则终止?但print(c.__class__.__mro__)显示所有类都在列表中,为何部分类的func未执行?
解答:
MRO是Python查找方法的优先级顺序,但它只是一个"查找路径",并非自动执行所有类方法的流程。super()的核心作用是主动沿着当前类的MRO顺序,调用下一个类的同名方法——如果没有调用super(),就不会触发后续MRO中类的方法执行,流程会在当前方法执行完毕后返回上一层。
具体对应场景来看:
- 场景2中,A类的
func去掉super()后,执行到A的func时,完成打印操作后直接执行后续代码,不会触发MRO中下一个类(B)的func,因此B和Base的func都不会执行。 - 场景3中,B类的
func去掉super(),所以执行到B的func时,不会调用Base的func,但A的super()仍会触发B的func执行,因此能看到B的输出,但看不到Base的。
简言之,MRO列表仅定义方法查找的优先级,不会自动遍历执行所有类的方法,只有通过super()主动发起调用,才会沿着MRO继续执行后续类的同名方法。
内容的提问来源于stack exchange,提问作者PopCornnnn

