Python中super()为何能调用多个父类方法?
Python多继承中super()的调用机制解析
核心误区纠正
你之前的误解在于认为super()只会返回MRO中首个匹配的方法并终止调用,但实际上super()的核心作用是沿着类的方法解析顺序(MRO)链条传递调用,只要每个父类的对应方法中也使用了super(),调用就会依次触发链条上的所有匹配方法。
实例拆解(以RealPyramid的例子为例)
假设示例中的类继承结构和__init__实现如下:
class Rectangle: def __init__(self, width, height): self.width = width self.height = height print("Rectangle.__init__") super().__init__() class Square(Rectangle): def __init__(self, side): self.side = side print("Square.__init__") super().__init__(side, side) class Triangle: def __init__(self): print("Triangle.__init__") super().__init__() class RightPyramid(Square, Triangle): def __init__(self, side, slant_height): self.slant_height = slant_height print("RightPyramid.__init__") super().__init__(side)
调用流程与MRO的关系
- 首先查看
RightPyramid的MRO:print(RightPyramid.__mro__) # 输出:(<class '__main__.RightPyramid'>, <class '__main__.Square'>, <class '__main__.Rectangle'>, <class '__main__.Triangle'>, <class 'object'>) - 当执行
RightPyramid(2, 3)时:- 先调用
RightPyramid.__init__,其中的super().__init__(side)会找到MRO中RightPyramid的下一个类Square,执行Square.__init__ Square.__init__中的super().__init__(side, side)找到MRO中Square的下一个类Rectangle,执行Rectangle.__init__Rectangle.__init__中的super().__init__找到MRO中Rectangle的下一个类Triangle,执行Triangle.__init__Triangle.__init__中的super().__init__找到MRO中Triangle的下一个类object,而object.__init__无实际操作,调用链条终止
- 先调用
这就是为什么你会看到Square、Rectangle、Triangle的__init__都被触发的原因——每个环节的super()都在传递调用。
关于super(RightPyramid).__init__指向Square.__init__的解释
super(类名)返回的是该类在MRO中下一个类的代理对象,所以super(RightPyramid).__init__确实指向Square.__init__,但这只是静态的类级别的指向。实际运行时,super()(不带参数或带self参数)是基于实例的完整MRO链条来动态传递调用的,而非仅停留在首个匹配的方法。
关键知识点总结
super()的本质不是“调用父类方法”,而是“调用MRO链条中的下一个方法”- 多继承下,只有当每个父类的方法都通过
super()传递调用时,才会触发链条上的所有匹配方法;若某个父类方法未使用super(),调用链条会在此中断 - 查看类的
__mro__属性是理解多继承调用顺序的核心手段
参考资料方向
- Python官方文档:重点阅读“方法解析顺序”(MRO)和
super()函数的章节,理解C3线性化算法(MRO的计算规则) - 《Python Cookbook》:第8章“类与对象”中关于多继承的章节,包含
super()的最佳实践和常见场景 - RealPython多继承专题:重点关注MRO链条传递和协作式多继承的实现方式
内容的提问来源于stack exchange,提问作者Lux
相关产品推荐
相关产品推荐

