You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python父类如何检测被子类重写的方法及对应子类类名

实现方案

Python 原生的类元信息能力完全可以覆盖这两个检测需求,不需要额外第三方依赖,核心用到两个内置能力:

  • 类的__subclasses__()方法:可以获取当前类的所有直接继承子类,递归遍历就能拿到所有层级的子类
  • 方法身份比对:如果子类重写了父类方法,子类持有的同名方法对象和父类原始方法对象不是同一个,直接用is判断即可

两个检测需求的具体实现逻辑

1. 识别父类中被子类重写的方法

  1. 先提取父类自身定义的普通方法(过滤掉__开头的内置特殊方法)
  2. 递归遍历所有层级的子类,逐个比对同名方法和父类原始方法的身份,不一致就标记为被重写
  3. 去重后就能得到所有被重写过的父类方法列表

2. 获取重写了指定方法的所有子类类名

  1. 递归遍历当前父类的所有层级子类(包含间接继承的子类)
  2. 对每个子类,检查指定方法是否定义在子类自身的属性字典中,且该方法和父类原始方法身份不一致
  3. 收集所有符合条件的子类的__name__属性即可

适配示例类结构的可运行代码

class Parent:
    @classmethod
    def get_all_subclasses(cls):
        """递归获取所有层级的子类"""
        subclasses = []
        for subclass in cls.__subclasses__():
            subclasses.append(subclass)
            subclasses.extend(subclass.get_all_subclasses())
        return subclasses

    @classmethod
    def get_overridden_methods(cls):
        """获取父类中所有被子类重写过的方法名"""
        # 提取父类自身定义的普通方法
        parent_methods = {
            method_name for method_name, method in cls.__dict__.items()
            if callable(method) and not method_name.startswith("__")
        }
        overridden = set()
        for subclass in cls.get_all_subclasses():
            for method_name in parent_methods:
                # 子类自身定义了同名方法,且和父类方法不是同一个,判定为重写
                if method_name in subclass.__dict__ and subclass.__dict__[method_name] is not cls.__dict__[method_name]:
                    overridden.add(method_name)
        return list(overridden)

    @classmethod
    def get_subclasses_override_method(cls, target_method_name):
        """获取重写了指定方法的所有子类类名"""
        if target_method_name not in cls.__dict__ or not callable(cls.__dict__[target_method_name]):
            raise ValueError(f"父类中不存在名为{target_method_name}的可调用方法")
        result = []
        for subclass in cls.get_all_subclasses():
            if target_method_name in subclass.__dict__ and subclass.__dict__[target_method_name] is not cls.__dict__[target_method_name]:
                result.append(subclass.__name__)
        return result

    def call_api(self):
        print("API is called")

    def use_call_api(self):
        # 实例方法内判断当前实例所属类是否重写了call_api
        if type(self).call_api is not Parent.call_api:
            print("检测到call_api被子类重写,执行前置逻辑")
            self.call_api()
        else:
            print("call_api未被重写,执行默认逻辑")
            self.call_api()


class Child(Parent):
    def call_api(self):
        print("call_api")


class Child2(Parent):
    def call_api(self):
        print("call_api2")


class Child3(Parent):
    def call_api(self):
        print("call_ap3")

    def use_call_api(self):
        print("custom call_api")


# 测试效果
if __name__ == "__main__":
    print("父类中被重写的方法:", Parent.get_overridden_methods())
    print("重写了call_api的子类:", Parent.get_subclasses_override_method("call_api"))
    print("重写了use_call_api的子类:", Parent.get_subclasses_override_method("use_call_api"))

    print("\n--- 父类实例调用use_call_api ---")
    p = Parent()
    p.use_call_api()

    print("\n--- Child实例调用use_call_api ---")
    c1 = Child()
    c1.use_call_api()

    print("\n--- Child3实例调用use_call_api ---")
    c3 = Child3()
    c3.use_call_api()

运行输出参考

父类中被重写的方法: ['use_call_api', 'call_api']
重写了call_api的子类: ['Child', 'Child2', 'Child3']
重写了use_call_api的子类: ['Child3']

--- 父类实例调用use_call_api ---
call_api未被重写,执行默认逻辑
API is called

--- Child实例调用use_call_api ---
检测到call_api被子类重写,执行前置逻辑
call_api

--- Child3实例调用use_call_api ---
custom call_api

注意事项

  • 不要用hasattr()判断方法是否重写,子类会继承父类方法,hasattr()永远返回True,必须直接检查子类自身的__dict__是否存在同名方法,再做身份比对
  • 多层继承场景(比如Child派生出GrandChild类)下,上述递归获取子类的逻辑可以正常覆盖
  • 实例方法内判断当前实例是否重写方法,必须用type(self)取实例所属类来比对方法,不要直接用self.方法名,绑定方法每次访问都会生成新对象,身份比对会出错

内容的提问来源于stack exchange,提问作者Seyed Mostafa SeyedAshoor

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 03:20:02