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

如何检测Python函数所应用的装饰器(基于functools.wraps)

解决方案

由于Python默认不会自动记录应用在函数上的装饰器信息——即便是使用functools.wraps,也仅会维护__wrapped__属性指向被包装的原函数。要实现获取装饰器列表或判断是否被特定装饰器装饰的功能,需要手动给装饰器添加标识,再通过遍历__wrapped__链来收集信息。

实现步骤

1. 给装饰器添加标识

我们可以给每个装饰器返回的包装器函数绑定一个属性,指向装饰器本身。为了避免重复代码,推荐写一个通用的标记装饰器:

from functools import wraps

# 通用装饰器,用于给目标装饰器添加标识
def mark_decorator(decorator):
    def wrapper(func):
        wrapped_func = decorator(func)
        # 给包装器绑定对应的装饰器引用
        wrapped_func.__decorator__ = decorator
        return wrapped_func
    return wrapper

然后用这个标记装饰器修饰你的自定义装饰器:

@mark_decorator
def decorator_wraps_1(function):
    @wraps(function)
    def _wrapper(*a, **kw):
        return function(*a, **kw)
    return _wrapper

@mark_decorator
def decorator_wraps_2(function):
    @wraps(function)
    def _wrapper(*a, **kw):
        return function(*a, **kw)
    return _wrapper

如果不想用通用标记,也可以直接在每个装饰器内部手动添加属性,效果完全一致:

def decorator_wraps_1(function):
    @wraps(function)
    def _wrapper(*a, **kw):
        return function(*a, **kw)
    _wrapper.__decorator__ = decorator_wraps_1
    return _wrapper

2. 实现装饰器列表获取与检查函数

通过遍历函数的__wrapped__链,收集所有绑定的装饰器:

def decorators(func):
    decorator_list = []
    current_func = func
    # 遍历包装链,直到没有__wrapped__属性
    while hasattr(current_func, '__wrapped__'):
        # 如果当前包装器有装饰器标识,加入列表
        if hasattr(current_func, '__decorator__'):
            decorator_list.append(current_func.__decorator__)
        # 跳转到下一层被包装的函数
        current_func = current_func.__wrapped__
    return decorator_list

def is_decorated_by(func, decorator):
    # 检查目标装饰器是否在装饰器列表中
    return decorator in decorators(func)

3. 测试验证

@decorator_wraps_1
@decorator_wraps_2
def foo(x, y):
    return x + y

# 获取装饰器名称列表
print([d.__name__ for d in decorators(foo)])  # 输出: ['decorator_wraps_1', 'decorator_wraps_2']
# 检查是否被指定装饰器装饰
print(is_decorated_by(foo, decorator_wraps_1))  # 输出: True
print(is_decorated_by(foo, decorator_wraps_2))  # 输出: True

注意事项

  • 该方案仅适用于你能控制的自定义装饰器,第三方装饰器需要看是否提供了类似的标识,或者通过包装第三方装饰器来添加__decorator__属性。
  • 依赖functools.wraps维护的__wrapped__属性,这是Python官方文档明确的公共属性,不存在内部实现变更的风险。
  • 装饰器的列表顺序与代码中@的顺序一致(最外层装饰器在前),符合调用时的触发顺序。

内容的提问来源于stack exchange,提问作者MattSom

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 13:45:38