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

被装饰者如何访问装饰器名称?以foo与a_decorator为例

在被装饰函数内部获取装饰器名称的实现方法

当然可以做到!这里有几种可靠的方式让你的foo函数获取到装饰器a_decorator的名称,从而打印出Called a_decorator,我会逐一说明实现思路和代码示例:

方法一:给被装饰函数添加自定义属性

这是最常用的方式,装饰器在包装原函数时,给返回的包装器(wrapper)添加一个存储装饰器名称的属性,被装饰后的函数可以直接访问这个属性。

import functools

def a_decorator(func):
    @functools.wraps(func)  # 保留原函数的元信息(比如__name__),避免混淆
    def wrapper(*args, **kwargs):
        return func(*args, **kwargs)
    
    # 给包装器添加装饰器名称属性
    wrapper._decorator_name = a_decorator.__name__
    return wrapper

@a_decorator
def foo():
    # 直接访问被装饰后函数的自定义属性
    print(f'Called {foo._decorator_name}')

foo()  # 输出:Called a_decorator

关键说明:

  • functools.wraps(func)不是必须的,但它能让wrapper继承原函数func的元数据(比如foo.__name__还是'foo'而不是'wrapper'),让代码更规范。
  • 我们给wrapper添加了_decorator_name属性,因为@a_decorator语法糖执行后,foo变量实际指向的是wrapper函数,所以可以直接通过foo._decorator_name获取装饰器名称。

方法二:通过参数传递装饰器名称

如果希望更显式地传递信息,可以让装饰器在调用原函数时,把装饰器名称作为参数传入,被装饰函数直接接收这个参数即可。

方式A:显式定义参数

def a_decorator(func):
    def wrapper(*args, **kwargs):
        # 调用原函数时传入装饰器名称
        return func(*args, decorator_name=a_decorator.__name__, **kwargs)
    return wrapper

@a_decorator
def foo(decorator_name):
    print(f'Called {decorator_name}')

foo()  # 输出:Called a_decorator

方式B:用关键字参数兼容原函数签名

如果不想修改原函数的参数列表,可以用**kwargs来接收装饰器传递的参数:

def a_decorator(func):
    def wrapper(*args, **kwargs):
        kwargs['decorator_name'] = a_decorator.__name__
        return func(*args, **kwargs)
    return wrapper

@a_decorator
def foo(**kwargs):
    decorator_name = kwargs.get('decorator_name')
    if decorator_name:
        print(f'Called {decorator_name}')

foo()  # 输出:Called a_decorator

被装饰者(decoratee)访问装饰器名称的核心逻辑

总结一下,被装饰函数要获取装饰器名称,本质上有两种路径:

  1. 属性访问:装饰器在包装过程中,将自身名称绑定到被装饰后的函数对象上,被装饰函数直接访问该属性。
  2. 参数传递:装饰器在调用被装饰函数时,主动将自身名称作为参数传入,被装饰函数通过参数接收。

两种方式各有优劣:

  • 属性访问方式不需要修改被装饰函数的签名,更隐蔽,适合不想对外暴露参数的场景。
  • 参数传递方式更直观,代码可读性更高,适合需要明确传递上下文信息的场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 08:10:24