Python super() 函数深度解析:从单继承到钻石继承的完整指南

纸上星河
纸上星河
发布时间:2026-10-14| 4人浏览过
原创

本文深入解析 Python 中 super() 函数的核心机制与用法。通过单继承、多继承及钻石继承(菱形继承)的典型案例,详细对比传统类名调用与 super() 调用的差异。重点讲解 super() 如何基于 MRO(方法解析顺序)自动处理父类调用,有效避免重复初始化资源浪费,并提供 Python 2.x 与 3.x 版本间的语法区别说明。

一、super() 函数的核心用途

在深入探讨 super() 之前,明确其设计初衷至关重要。

  • 该函数主要用于子类中调用父类的方法。
  • 它广泛应用于多继承场景,旨在解决方法解析顺序(MRO)的查找逻辑以及钻石继承结构中的重复调用问题。

二、super() 的基础语法与机制

其标准语法格式如下:


super([type[, object-or-type]])

函数功能描述:

该函数返回一个代理对象,负责将后续的方法调用委托给 type 参数所指定类的父类或兄弟类。

参数详细说明:

type:指定类,为可选参数;object-or-type:指定对象或类,通常传入 self,也是可选参数。

返回值说明:

返回一个 super object 类型的代理对象。

官方 help 帮助信息解读:


>>> help(super)
Help on class super in module builtins:
 
class super(object)
 |  super() -> same as super(__class__, <first argument>)
 |  super(type) -> unbound super object
 |  super(type, obj) -> bound super object; requires isinstance(obj, type)
 |  super(type, type2) -> bound super object; requires issubclass(type2, type)
 |  Typical use to call a cooperative superclass method:
 |  class C(B):
 |      def meth(self, arg):
 |          super().meth(arg)
 |  This works for class methods too:
 |  class C(B):
 |      @classmethod
 |      def cmeth(cls, arg):
 |          super().cmeth(arg)
 
... ...
  • super 本身是继承自 object 的一个类,因此调用 super() 实际上等同于实例化 super 类。
  • 依据官方文档,super() 返回的 super object 本质上就是一个代理对象。
  • super() 支持四种不同的参数组合形式。
  • 此外,super() 同样适用于类的静态方法调用场景。

三、典型应用场景分析

3.1 单继承场景下的应用

首先分析一个最基础的子类调用父类方法的示例:


>>> class A:
        def funxx(self):
            print("执行 A 中的 funxx 方法 ... ...")
 
        
>>> class B(A):
        def funxx(self):
            A.funxx(self)       # 通过类名调用父类中的同名方法,self 参数代表 B 类的实例对象 b
            print("执行 B 中的 funxx 方法 ... ...")
 
        
>>> b = B()
>>> b.funxx()
执行 A 中的 funxx 方法 ... ...
执行 B 中的 funxx 方法 ... ...
  • 定义一个继承自 A 类的子类 B,并在 B 类中重写 funxx() 方法。B 中的 funxx() 旨在拓展 A 中 funxx() 的功能。
  • 由于需要保留 A 类 funxx() 的原有功能,因此必须在子类 B 中显式调用父类的同名方法以执行原有逻辑。
  • 在上述示例中,通过 A 类类名直接调用 A 中的同名方法,此时第一个参数 self 实际传递的是 B 类的实例 b。

改用 super() 函数来实现对父类方法的调用:


>>> class A:
        def funxx(self):
            print("执行 A 中的 funxx 方法 ... ...")
 
        
>>> class B(A):
        def funxx(self):
            super().funxx()
            print("执行 B 中的 funxx 方法 ... ...")
 
		
>>> b = B()
>>> b.funxx()
执行 A 中的 funxx 方法 ... ...
执行 B 中的 funxx 方法 ... ...
  • 对比执行结果可知,其输出效果与传统类名调用的结果完全一致。
  • 官方文档指出,在单继承的类层级结构中,使用 super 引用父类无需显式指定父类名称,从而显著提升代码的可维护性。
  • 这意味着在子类中不再依赖父类名来调用父类方法,而是通过代理对象完成调用。当父类名称变更或继承关系调整时,无需逐一修改每个调用点。

3.2 单继承场景的进阶探讨

在 help() 的帮助信息中,明确指出类中使用 super() 不带参数的形式,在语义上等同于 super(__class__, <first argument>) 这种显式传参形式。这也是 Python 2.x 与 Python 3.x 在处理 super() 时的主要区别所在。

基于上述原理改写之前的单继承问题代码:


>>> class A:
        def funxx(self):
            print("执行 A 中的 funxx 方法 ... ...")
 
		
>>> class B(A):
        def funxx(self):
	        super(B, self).funxx()
	        print("执行 B 中的 funxx 方法 ... ...")
 
		
>>> b = B()
>>> b.funxx()
执行 A 中的 funxx 方法 ... ...
执行 B 中的 funxx 方法 ... ...
  • 基础调用方式 A.funxx(self),其中 self 指代实例对象 b。用自然语言描述即:实例对象 b 通过 A 类名调用方法 funxx()。
  • 官方描述指出:返回一个代理对象,它会将方法调用委托给 type 的父类或兄弟类。用自然语言描述即:代理对象 super 通过 type 的父类或兄弟类调用其中的方法。
  • 我们发现 super 是通过参数设置来选择调用哪个父类的方法。其中第二个参数提供了 MRO(方法解析顺序),即搜索目标方法的顺序,而第一个参数则限定了搜索目标方法的范围。
  • 例如 super(B, self),第一个参数为 B,第二个参数 self 为实例 b,其所在类的继承顺序(MRO)为:B→A→object。因此调用时,系统会在 B 的父类 A 中寻找目标方法,若 A 中未找到,则继续向上层 object 中查找。

具体示例如下:


class A:
    pass
 
 
class B(A):
    pass
 
 
class C(A):
    def funxx(self):
        print("找到 funxx() 位于 C 中...")
 
 
class D(A):
    pass
 
 
class E(B, C):
    pass
 
 
class F(E, D):
    def funff(self):
        print("执行 F 中的 funff()...")
        super(E, self).funxx()
 
        
print(f"F 类的 MRO : {F.__mro__}")
f = F()
f.funff()

运行结果如下:


F 类的 MRO : (<class '__main__.F'>, <class '__main__.E'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.D'>, <class '__main__.A'>, <class 'object'>)
执行 F 中的 funff()...
找到 funxx() 位于 C 中...
  • 从结果可以清晰看出 F 类的 MRO 顺序为:F→E→B→C→D→A→object。
  • 在 super() 函数中,第一个参数指定为 E,目标是调用 E 类的父类 B 中的 funxx() 方法。由于 B 类中未找到该方法,系统继续在 B 类的兄弟类 C 中查找并成功找到,符合预期逻辑。

3.3 重复调用问题(钻石继承)

重复调用问题也被称为钻石继承问题或菱形图问题。

先观察普通调用方法在以下场景中的表现:


>>> class A:
        def __init__(self):
            print("打印属性 a")
 
	    
>>> class B(A):
        def __init__(self):
            print("打印属性 b")
            A.__init__(self)
 
	    
>>> class C(A):
        def __init__(self):
            print("打印属性 c")
            A.__init__(self)
 
	    
>>> class D(B, C):
        def __init__(self):
            print("打印属性 d")
            B.__init__(self)
            C.__init__(self)
 
	    
>>> d = D()
打印属性 d
打印属性 b
打印属性 a
打印属性 c
打印属性 a
  • 由于 B 和 C 均继承自 A,当 D 进行实例化时,A 的构造函数被执行了两次。这就是典型的重复调用问题。
  • 显然,我们只需调用一次即可,重复调用只会造成不必要的资源浪费。

接下来演示如何使用 super() 函数来解决此问题:


>>> class A:
        def __init__(self):
            print("打印属性 a")
 
	    
>>> class B(A):
        def __init__(self):
            print("打印属性 b")
            super().__init__()                # super() 等同于 super(B, self)
 
	    
>>> class C(A):
        def __init__(self):
            print("打印属性 c")
            super().__init__()                # super() 等同于 super(C, self)
 
	    
>>> class D(B, C):
        def __init__(self):
            print("打印属性 d")
            super(D, self).__init__()
 
	    
>>> d = D()
打印属性 d
打印属性 b
打印属性 c
打印属性 a
  • 查看输出结果发现,虽然重复调用问题得以解决,但输出顺序与直觉有所差异。我们的惯性思维预期是:先执行 D 类的 __init__() 方法,接着调用 B 类的 __init__() 方法,B 类的构造方法中又调用了父类 A 的 __init_() 方法,然后再调用 C 类的 __init_() 方法,该方法也调用了父类 A 的 __init__() 方法。因此预期执行顺序应为:打印属性 d,打印属性 b,打印属性 a,打印属性 c。
  • 为何实际结果并非如此?首先需明确,D 类中的第二个参数 self 为 D 的实例 d,它提供的 MRO 为:D→B→C→A→object。因此 D 类中的 super() 函数产生的是 d 的代理对象,当其调用父类 B 的 __init__() 时,B 的 super() 的第二个参数为 D 中的 super object,其所提供的 MRO 依旧保持为:D→B→C→A→object。这意味着 B 中的 super() 调用的是其上一级 C 中的 __init__(),而非 A 中的 __init__()。因此实际执行结果为:打印属性 d,打印属性 b,打印属性 c,打印属性 a。

3.4 super(type) 单独使用的注意事项


>>> class A:
	    def funxx(self):
		    print("...A...")
 
		
>>> class B(A):
	    def funxx(self):
		    print("...B...")
 
		
>>> sa = super(B)
>>> print(sa)
<super: <class 'B'>, NULL>
>>> print(type(sa))
<class 'super'>

可以看出,仅使用 super(type) 返回的是一个无效对象,或者称为未绑定的 super object。

至此,关于 Python super() 函数用法的总结介绍完毕。如需了解更多相关 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 算法库。