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

用函数装饰装饰器为何失效?两种写法差异原因咨询

装饰器装饰行为的疑惑解答

先明确你定义的装饰器工具:

def decorator_for_decorator(func):
    def wrapper(*args):
        print('Decorator successfully decorated')
        return func(*args)
    return wrapper

你困惑的是两种装饰方式的输出差异,本质是装饰的对象和触发时机完全不同。


第一种写法:装饰的是「装饰器函数本身」

代码如下:

# 你认为不生效的写法
@decorator_for_decorator
def decorator(func):
    def wrapper(*args):
        print('Function successfully decorated')
        return func(*args)
    return wrapper

def apply_decorator(func):
    func = decorator(func)
    return func

def f1():
    print('hello')

f2 = apply_decorator(f1)
f2()

输出:

Function successfully decorated
hello

为什么你觉得没生效?

@decorator_for_decorator直接装饰decorator函数,意味着decorator变量现在指向decorator_for_decorator返回的wrapper。它的触发时机是调用装饰器包装函数的时候,而不是调用被包装后的函数:

  1. 执行f2 = apply_decorator(f1)时,会调用decorator(f1)——也就是调用decorator_for_decorator的wrapper,这时候会打印Decorator successfully decorated,但这一步的输出被你忽略了(你只关注了f2()的输出)
  2. 调用f2()时,执行的是原decorator返回的内部wrapper,所以只会打印后面两行

第二种写法:装饰的是「装饰器返回的包装函数」

代码如下:

# 你认为生效的写法
def decorator(func):
    @decorator_for_decorator
    def wrapper(*args):
        print('Function successfully decorated')
        return func(*args)
    return wrapper

f2 = apply_decorator(f1)
f2()

输出:

Decorator successfully decorated
Function successfully decorated
hello

为什么这时候生效?

这里的@decorator_for_decorator装饰的是decorator内部的wrapper——也就是装饰器最终返回给被装饰函数的包装层。触发时机是调用被包装后的函数时:

  1. apply_decorator(f1)执行时,decorator(f1)返回的是被decorator_for_decorator装饰过的wrapper
  2. 调用f2()时,先执行decorator_for_decorator的wrapper打印第一行,再执行原wrapper打印第二行,最后调用f1()打印第三行

总结

  • 第一种写法:给「装饰器函数本身」加装饰,打印出现在用装饰器包装目标函数的阶段
  • 第二种写法:给「装饰器生成的包装函数」加装饰,打印出现在调用被包装函数的阶段

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 03:24:53