用函数装饰装饰器为何失效?两种写法差异原因咨询
装饰器装饰行为的疑惑解答
先明确你定义的装饰器工具:
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。它的触发时机是调用装饰器包装函数的时候,而不是调用被包装后的函数:
- 执行
f2 = apply_decorator(f1)时,会调用decorator(f1)——也就是调用decorator_for_decorator的wrapper,这时候会打印Decorator successfully decorated,但这一步的输出被你忽略了(你只关注了f2()的输出) - 调用
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——也就是装饰器最终返回给被装饰函数的包装层。触发时机是调用被包装后的函数时:
apply_decorator(f1)执行时,decorator(f1)返回的是被decorator_for_decorator装饰过的wrapper- 调用
f2()时,先执行decorator_for_decorator的wrapper打印第一行,再执行原wrapper打印第二行,最后调用f1()打印第三行
总结
- 第一种写法:给「装饰器函数本身」加装饰,打印出现在用装饰器包装目标函数的阶段
- 第二种写法:给「装饰器生成的包装函数」加装饰,打印出现在调用被包装函数的阶段
内容的提问来源于stack exchange,提问作者DLim
相关产品推荐
相关产品推荐

