ZetCode

Python super 函数

上次修改时间:2025 年 4 月 11 日

本综合指南探讨了 Python 的 super 函数,它可以在继承层次结构中实现对父类的方法调用。我们将涵盖基本用法、方法解析顺序和实际示例。

基本定义

super 函数返回一个代理对象,该对象将方法调用委托给父类或兄弟类。这对于 Python 中的协作多重继承至关重要。

主要特征:遵循方法解析顺序 (MRO),适用于单继承和多重继承,并有助于避免硬编码父类名称。

基本继承用法

这是一个简单的用法示例,展示了 super 如何在单继承场景中调用父类方法。

basic_super.py
class Parent:
    def __init__(self):
        print("Parent __init__")
        
    def method(self):
        print("Parent method")

class Child(Parent):
    def __init__(self):
        super().__init__()
        print("Child __init__")
        
    def method(self):
        super().method()
        print("Child method")

c = Child()
c.method()

此示例演示了基本的 super 用法。Child 类调用 Parent 的方法,而无需显式命名 Parent,从而使代码更易于维护。

输出显示父方法和子方法都执行,由于 super 委托,父方法首先被调用。

多重继承

super 在多重继承中变得特别强大。此示例显示了菱形模式继承和方法解析。

multiple_inheritance.py
class A:
    def method(self):
        print("A method")
        super().method()

class B:
    def method(self):
        print("B method")

class C(A, B):
    def method(self):
        print("C method")
        super().method()

c = C()
c.method()
print(C.__mro__)  # Show method resolution order

这演示了 super 如何遵循 MRO (C → A → B)。即使 A 不继承自 B,每个类的方法都会调用链中的下一个类。

MRO 输出显示了 Python 用于解析方法调用的线性化继承路径。

super 与类方法

super 也适用于类方法。此示例显示了在 classmethod 上下文中的正确用法。

classmethod_super.py
class Base:
    @classmethod
    def create(cls):
        print(f"Base.create({cls})")
        return cls()

class Derived(Base):
    @classmethod
    def create(cls):
        print(f"Derived.create({cls})")
        instance = super().create()
        print(f"Created {instance}")
        return instance

d = Derived.create()

该示例显示了 classmethod 中的 super 正确地将派生类 (cls) 传递给父类的 classmethod。这保持了适当的多态性。

输出演示了调用链,并显示了通过继承层次结构的实例创建过程。

super 在属性覆盖中

此示例演示了如何使用 super 来扩展属性行为,而无需完全覆盖它。

property_super.py
class Person:
    def __init__(self, name):
        self._name = name
    
    @property
    def name(self):
        return self._name
    
    @name.setter
    def name(self, value):
        self._name = value

class Employee(Person):
    @property
    def name(self):
        return super().name.upper()
    
    @name.setter
    def name(self, value):
        super(Employee, Employee).name.__set__(self, value)

e = Employee("John")
print(e.name)  # JOHN
e.name = "Alice"
print(e.name)  # ALICE

Employee 类扩展了 name 属性 getter,同时保留了父类的 setter 行为。请注意属性 setter 所需的特殊语法。

当您希望修改属性行为,同时保留底层存储机制时,此模式非常有用。

super 与 __init_subclass__

Python 3.6+ 引入了 __init_subclass__。此示例显示了 super 如何使用此特殊类方法。

init_subclass.py
class PluginBase:
    plugins = []
    
    def __init_subclass__(cls, **kwargs):
        super().__init_subclass__(**kwargs)
        cls.plugins.append(cls)
        print(f"Registered plugin {cls.__name__}")

class PluginA(PluginBase):
    pass

class PluginB(PluginBase):
    pass

print(PluginBase.plugins)  # [<class '__main__.PluginA'>, <class '__main__.PluginB'>]

该示例演示了一个插件注册系统。每个子类都调用 super().__init_subclass__ 以确保正确的初始化链接。

此模式在需要跟踪基类的所有子类的框架中很常见。

最佳实践

资料来源

作者

我叫 Jan Bodnar,是一位充满激情的程序员,拥有丰富的编程经验。 自 2007 年以来,我一直在撰写编程文章。 迄今为止,我已经撰写了 1,400 多篇文章和 8 本电子书。 我拥有超过十年的编程教学经验。

列出所有 Python 教程