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

如何实现Python类装饰器?将子类方法添加至待处理函数列表

问题描述

想要实现一个Python装饰器,能将函数添加到对应类的函数列表中,后续可对这些函数统一处理。尝试的示例代码存在问题:装饰函数时需要传入子类的cls,但类定义完成前无法直接引用子类,常规包装函数方法无法解决这个矛盾:

class A:
    # 每个子类都应定义_list
    @classmethod
    def decorator(cls, f):
        # 期望cls是子类B
        cls._flist.append(f)
        return f

    @classmethod
    def processFunctions(cls):
        for f in cls._flist:
            ...

class B(A):
    _flist = []

    @B.decorator # 此处不可行,类B尚未定义完成
    def foo(self):
        print("Inside foo")
可行的实现方案

方法1:使用元类(最推荐)

元类可以在类创建的最后阶段介入,遍历类成员并收集目标函数,完美避开类未定义的问题:

class FunctionCollectorMeta(type):
    def __new__(cls, name, bases, attrs):
        # 创建类实例
        new_class = super().__new__(cls, name, bases, attrs)
        # 初始化子类的函数列表
        new_class._flist = []
        # 遍历类属性,筛选带标记的函数
        for attr_name, attr_value in attrs.items():
            if hasattr(attr_value, '_need_collect'):
                new_class._flist.append(attr_value)
        return new_class

# 基础类使用自定义元类
class A(metaclass=FunctionCollectorMeta):
    @classmethod
    def processFunctions(cls):
        print(f"处理 {len(cls._flist)} 个函数")
        for func in cls._flist:
            print(f"目标函数: {func.__name__}")

# 定义标记用的装饰器
def collect(func):
    func._need_collect = True
    return func

# 子类实现
class B(A):
    @collect
    def foo(self):
        print("Inside foo")

    @collect
    def bar(self):
        print("Inside bar")

# 测试调用
B.processFunctions()

运行后输出:

处理 2 个函数
目标函数: foo
目标函数: bar

方法2:类装饰器(无需元类)

如果不想使用元类,可以用类装饰器在类定义完成后统一收集函数:

# 标记函数的装饰器
def collect(func):
    func._need_collect = True
    return func

class A:
    @classmethod
    def processFunctions(cls):
        print(f"处理 {len(cls._flist)} 个函数")
        for func in cls._flist:
            print(f"目标函数: {func.__name__}")

# 类装饰器:遍历类成员并收集标记函数
def collect_functions(cls):
    cls._flist = []
    for attr_name, attr_value in cls.__dict__.items():
        if hasattr(attr_value, '_need_collect'):
            cls._flist.append(attr_value)
    return cls

# 子类应用类装饰器
@collect_functions
class B(A):
    @collect
    def foo(self):
        print("Inside foo")

    @collect
    def bar(self):
        print("Inside bar")

# 测试调用
B.processFunctions()

方法3:延迟绑定装饰器(手动初始化)

这种方法兼容原有的装饰器思路,但需要手动完成函数列表的初始化,适合对原有代码改动较小的场景:

class A:
    # 用父类存储待绑定的函数
    _pending_funcs = []

    @classmethod
    def decorator(cls, func):
        cls._pending_funcs.append(func)
        return func

    @classmethod
    def processFunctions(cls):
        print(f"处理 {len(cls._flist)} 个函数")
        for func in cls._flist:
            print(f"目标函数: {func.__name__}")

# 子类定义
class B(A):
    _flist = []

    @A.decorator
    def foo(self):
        print("Inside foo")

# 手动将待绑定函数转移到子类列表
B._flist.extend(A._pending_funcs)
A._pending_funcs.clear() # 避免影响其他子类

# 测试调用
B.processFunctions()

内容的提问来源于stack exchange,提问作者David Davó

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 08:45:37