Python 继承、方法重写与 super

说明 Python 中继承如何复用行为,方法重写如何扩展父类逻辑,以及 super 为什么表示沿 MRO 向后协作而不只是“调父类”。

#type / concept #status / growing #resource / python #tech / lang / python

[!info] related notes

Python 继承、方法重写与 super

一句话定义

继承让子类复用父类已有状态和行为,方法重写让子类改写同名行为,而 super() 的真正含义是“沿当前 MRO 找下一个实现继续协作”。

核心机制 / 工作原理

1. 继承表达的是“在已有基础上继续定义”

class Child(Parent): 出现时,子类会继承父类的一部分属性和方法。这样做的价值不是少写几行代码,而是让“共性行为”集中定义,“差异行为”留给子类扩展。

2. 方法重写是在子类里重新定义同名行为

如果子类定义了和父类同名的方法,实例调用时会优先用子类实现。这让子类既可以:

  • 完全替换父类行为
  • 或者在父类行为前后加上自己的逻辑

3. super() 不是“硬编码调用父类”

很多人把 super() 理解成“去调直接父类”,这在简单例子里看起来像对的,但更准确的说法是:

super() 会按照当前类的 MRO,去找“下一个应该被调用的实现”。

这也是它能在多重继承里协作的根本原因。

4. 初始化也应该遵守协作式调用

如果子类重写 __init__,通常也应该先用 super().__init__(...) 初始化父类部分状态,再补自己的字段。这样能保证整条继承链的初始化顺序清晰,也为以后扩展成多重继承保留空间。

最小例子 / 最小场景

class Person:
    def __init__(self, name: str):
        self.name = name

    def introduce(self) -> str:
        return f"I am {self.name}"


class Employee(Person):
    def __init__(self, name: str, employee_id: str):
        super().__init__(name)
        self.employee_id = employee_id

    def introduce(self) -> str:
        base = super().introduce()
        return f"{base}, employee id = {self.employee_id}"


e = Employee("Alice", "E-01")
print(e.introduce())

这里 Employee 没有重复定义 name 的初始化逻辑,而是复用了 Person 的构造过程;introduce 则通过 super() 把父类结果拼接成更具体的版本。

边界与易混淆点

  1. 直接写 Parent.method(self, ...) 会把依赖关系写死,后续一旦进入多重继承,就可能破坏协作链。
  2. 重写方法时最好保持输入输出语义稳定,否则“看起来是子类,实际上换了契约”,可替换性会很差。
  3. 如果你的目标只是“组合两个对象协作”,而不是表达清晰的层级复用关系,组合通常比继承更稳。
创建于 2026/5/20 更新于 2026/5/27