【发布时间】:2020-12-01 20:14:48
【问题描述】:
偶然遇到python装饰器的一个奇怪问题,基本上我直接调用装饰器函数时,原来被包装的函数被包装了两次。
一些简单的代码来说明问题:
def my_deco(f):
def wrapper(*args):
print('some code before')
f(*args)
print('some code after')
return wrapper
@my_deco
def original_func(text):
print (f'original func print {text}')
然后命令1):
original_func('hello')
将打印(顺便说一句,这是正确的):
some code before
original func print hello
some code after
但是命令2):
my_deco(original_func)('hello')
将在下面打印:
some code before
some code before
original func print hello
some code after
some code after
期望两个命令之间的结果相同,但后一个命令似乎将原始函数包装了两次。当我在不带括号的情况下运行这两个命令时,它们都正确地指向了包装函数,但是一旦使用括号执行,结果就会不同。
我有点说服自己有以下逻辑,但仍然感到不舒服,所以我正在寻找 cmet 或纠正我的想法:
命令1):调用 original_func -> my_deco -> wrapper -> wrapping + original_func 执行
命令2):调用my_deco -> wrapper -> wrapping + original_func 执行(是wrapped版本)
所以看起来命令 1) 中的 original_func 仍然是“原始”,没有包装;并且命令 2) 中的 original_func 是“包装”版本。
提前致谢。
【问题讨论】:
-
嗯...是的。你把它包了两次。为什么要两次应用装饰器?
-
这是无意的,显然只是一次。
-
那是因为运行
my_deco(original_func)('hello')调用了装饰器,而不是再次调用装饰器(因为 original_func 被 my_deco 包装)然后是原始 func。