深入解析Python中super()方法的调用机制与MRO原理

Ivy
Ivy
发布时间:2026-10-13| 3人浏览过
原创

本文深入剖析Python中super()方法的底层原理,重点讲解C3算法生成的MRO(方法解析顺序)列表。通过对比Python 2与Python 3的新式类差异,结合钻石继承案例,阐明广度优先调用机制及子类实例传递逻辑,帮助开发者准确掌握多继承中的方法调用顺序。

一、前言

在Python面向对象编程中,继承是一个核心概念。初学者往往觉得它功能强大,其中涉及的super类也频繁出现。近期通过实际编码练习,我才真正理清了它的运作逻辑。特此整理分享,供后续研究者参考,毕竟如今编程教育已日益普及。

二、代码示例与分析

直接展示核心代码,若能正确回答下方问题,即可跳过后续详解。

class A():
  def go(self):
    print ("go A go!")
  def stop(self):
    print ("stop A stop!")
  def pause(self):
    raise Exception("Not Implemented")
class B(A):
  def go(self):
    super(B, self).go()
    print ("go B go!")
class C(A):
  def go(self):
    super(C, self).go()
    print ("go C go!")
  def stop(self):
    super(C, self).stop()
    print ("stop C stop!")
class D(B,C):
  def go(self):
    super(D, self).go()
    print ("go D go!")
  def stop(self):
    super(D, self).stop()
    print ("stop D stop!")
  def pause(self):
    print ("wait D wait!")
class E(B,C):
  pass
a = A()
b = B()
c = C()
d = D()
e = E()
# 说明下列代码的输出结果
a.go()
print('--------')
b.go()
print('--------')
c.go()
print('--------')
d.go()
print('--------')
e.go()
print('--------')
a.stop()
print('--------')
b.stop()
print('--------')
c.stop()
print('--------')
d.stop()
print('--------')
e.stop()
print(D.mro())
a.pause()
b.pause()
c.pause()
d.pause()
e.pause()

虽然直接运行代码可得结果,但建议先自行推导。初次看到执行结果时,其输出顺序可能令人意外。

step1:

需明确几个基础概念:

继承的主要功能:实现父类代码的复用。

多态的功能:同一方法针对不同对象类型产生相应不同的结果。

开闭原则:软件实体应对扩展开放,对修改封闭。

super类的功能:在新式类中实现广度优先且不重复的父类调用,从而解决钻石继承(多继承)带来的难题。

step2:

super的实现原理:基于C3算法生成MRO(Method Resolution Order,方法解析顺序)列表,依据该列表中元素的顺序进行查询和调用。

新式类的调用顺序为广度优先,而旧式类为深度优先。

step3:

个人理解要点:

1. 调用父类方法时,传入的是子类的实例对象。

2. 在新式类子类(如A, B)中,A出现在B之前。

3. super类似一种嵌套设计:当代码执行到super实例化后,先查找同级父类;若无其他父类,则执行自身父类,再向下继续。

简洁概括为三个原则:

子类在父类之前列出,所有类不重复调用,顺序从左到右。

理解上述规则后,相关题目即可迎刃而解。

无需再运行代码,答案如下:

a.go()# go A go!
b.go()# go A go!# go B go!
c.go()# go A go!# go C go!
d.go()# go A go!# go C go!# go B go!# go D go!
e.go()# go A go!# go C go!# go B go!
a.stop()# stop A stop!
b.stop()# stop A stop!
c.stop()# stop A stop!# stop C stop!
d.stop()# stop A stop!# stop C stop!# stop D stop!
e.stop()# stop A stop!
a.pause()# ... Exception: Not Implemented
b.pause()# ... Exception: Not Implemented
c.pause()# ... Exception: Not Implemented
d.pause()# wait D wait!
e.pause()# ...Exception: Not Implemented

观察答案后,还有一个细节值得注意:若父类抛出异常,而子类有未抛出异常的方法,则该异常不会被抛出。这一设计在实际应用中颇具价值。

此处中间A,C,B,D的顺序与网上常见示例略有不同,这促使我深入研究,主要对应个人理解中的第三条。

补充说明:

Python 2与Python 3在此问题上的差异

Python 2默认不继承object类。

Python 3默认所有类均继承object类,均为新式类。

Python 2中super调用方式为:super(开始类名,self).函数名()。

Python 3中super调用简化为:super().函数名()。

关于调用父类函数时传入子类实例的示例如下:

class A:
  def __init__(self):
    self.n = 2
  def add(self, m):
    print('self is {0} @A.add'.format(self))
    self.n += m
class B(A):
  def __init__(self):
    self.n = 3
  def add(self, m):
    print('self is {0} @B.add'.format(self))
    super().add(m)
    print('newb')
    self.n += 3
class C(A):
  def __init__(self):
    self.n = 4
  def add(self, m):
    print('self is {0} @C.add'.format(self))
    super().add(m)
    print('newc')
    self.n += 4
class D(B, C):
  def __init__(self):
    self.n = 5
  def add(self, m):
    print('self is {0} @D.add'.format(self))
    super().add(m)
    self.n += 5
d = D()
d.add(2)
print(d.n)

总结

以上介绍了Python中super()的用法和原理,希望对大家有所帮助。如有疑问请留言,小编会及时回复。感谢大家对本站的支持!

相关标签:

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。