Python 定义一个子类继承父类,并在子类中重写一个方法(千字长文)

Python 定义一个子类继承父类,并在子类中重写一个方法

核心概念

继承是面向对象编程的核心特性之一,允许子类直接复用父类的属性和方法。方法重写(Override)指子类定义与父类同名的方法,实现对父类行为的定制。这在需要扩展类功能或调整已有逻辑时非常有用。例如,动物类定义基础行为,子类狗/猫/鸟可以重写发声方法。

基础语法

类继承定义

class Animal:
    def speak(self):
        print("动物发出声音")  # 父类基础实现

class Dog(Animal):  # 继承Animal类
    def speak(self):  # 重写speak方法
        print("汪汪汪")  # 子类定制行为

super()函数调用

class Cat(Animal):
    def speak(self):
        super().speak()  # 调用父类方法
        print("喵喵喵")  # 补充子类逻辑

多继承示例

class A:
    def show(self):
        print("A类方法")

class B:
    def show(self):
        print("B类方法")

class C(A, B):  # 多继承
    def show(self):
        print("C类方法")  # 优先使用自己的方法

进阶特性

特性 说明 示例代码
方法绑定 子类方法自动绑定实例 c = C(); c.show()
super()链式 支持多层继承调用 super().method()
MRO顺序 方法解析顺序影响调用路径 C.__mro__
抽象方法 需强制实现的基类方法 from abc import ABC, abstractmethod

完整多继承演示:

class Base:
    def action(self):
        print("基础操作")

class Extender1(Base):
    def action(self):
        print("扩展1逻辑")
        super().action()  # 保持父类调用链

class Extender2(Base):
    def action(self):
        print("扩展2逻辑")

class Final(Extender1, Extender2):  # 继承顺序影响MRO
    def action(self):
        print("最终实现")
        super().action()  # 优先调用Extender1

f = Final()
f.action()  # 输出顺序体现继承优先级

实战应用

图形面积计算系统

class Shape:
    def area(self):
        raise NotImplementedError  # 强制子类实现

class Rectangle(Shape):
    def __init__(self, w, h):
        self.width = w  # 宽度参数
        self.height = h  # 高度参数

    def area(self):
        return self.width * self.height  # 重写基础方法

class Circle(Shape):
    def __init__(self, r):
        self.radius = r  # 半径参数

    def area(self):
        return 3.14159 * self.radius**2  # 重写基础方法

日志系统扩展

class Logger:
    def log(self, message):
        print(f"[LOG] {message}")  # 基础日志记录

class FileLogger(Logger):
    def log(self, message):
        with open("log.txt", "a") as f:  # 打开日志文件
            f.write(f"[FILE] {message}\n")  # 重写日志方式

注意事项

  1. 方法签名不一致:子类重写方法参数必须与父类完全匹配,否则会引发TypeError。例如父类定义def speak(self, volume),子类实现必须包含相同参数。
  2. 大小写混用:重写方法名需完全匹配大小写,Python区分大小写(如Speakspeak)。
  3. 多重继承优先级:继承顺序决定方法解析优先级,建议通过ClassName.__mro__查看具体解析顺序。
  4. super()使用陷阱:在多继承场景中错误使用super()可能导致方法调用遗漏,应结合继承图理解调用链。

高级技巧

动态方法重写

class DynamicOverride:
    def greet(self):
        print("原始问候")

obj = DynamicOverride()
obj.greet = lambda: print("动态覆盖")  # 运行时方法替换
obj.greet()  # 执行新绑定的方法

保留父类逻辑的装饰器

def override(parent_method):
    def decorator(func):
        def wrapper(self, *args, **kwargs):
            parent_method(self, *args, **kwargs)  # 调用父类方法
            return func(self, *args, **kwargs)  # 执行子类方法
        return wrapper
    return decorator

class Parent:
    @override(lambda self: print("父类预处理"))
    def prepare(self):
        print("父类核心处理")

class Child(Parent):
    @override(Parent.prepare)  # 使用装饰器继承
    def prepare(self):
        print("子类定制处理")

多继承冲突解决方案

class A:
    def show(self):
        print("A")

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

class C(A, B):  # 明确继承顺序
    def show(self):
        A.show(self)  # 手动调用指定父类
        B.show(self)  # 显式调用所有需要的方法

常见问题

Q: 为什么调用super()时会出现无限递归?
A: 子类实现中错误调用了自身方法而非父类方法,例如在Dog类中误写成super().speak()指向了Dog.speak自身。

Q: 如何判断是否需要重写方法?
A: 当子类行为需要与父类完全一致但实现逻辑不同时(如数据结构差异),或需要扩展父类行为时(如增加前置处理),才需要重写。

Q: 多继承中多个父类都有同名方法怎么办?
A: 通过继承顺序控制优先级,或使用显式调用ClassName.method(self)避免super()的自动解析规则。

Q: 重写方法如何访问父类被覆盖的属性?
A: 使用super().__init__()初始化父类属性,或通过super().attribute_name访问父类属性。