我试图在Python中学习装饰器,每当我想到它时,我遇到了一个像这样的问题。我无法弄清楚为什么来自my_func
的打印声明不会显示,而是我得到了“无”#39;回。如果我在我的包装器func
中的return语句中包含return (func, wrapper)
,则会收到错误,指出元组对象不可调用。这个例子有什么问题?
def my_dec(func):
def wrapper():
decoration = "decorated"
print(decoration)
return wrapper
@my_dec
def my_func():
a = "Original"
print (a)
print(my_func())
答案 0 :(得分:4)
您永远不会在func
中调用已包裹的wrapper
。添加呼叫,例如:
def my_dec(func):
def wrapper():
decoration = "decorated"
print(decoration)
# Call the decorated function and return what it returns
return func()
return wrapper
@my_dec
def my_func():
a = "Original"
print (a)
print(my_func())
现在会生成(自func()
implicitly returns None
):
decorated
Original
None
如果我在我的包装器
func
中的return语句中包含return func, wrapper
,则会收到错误消息,指出tuple对象不可调用。
错误必须来自你做的事情:
def my_dec(func):
def wrapper():
decoration = "decorated"
print(decoration)
# Now `my_dec` returns a tuple instead of a function
return func, wrapper
请记住装饰is (roughly) equivalent to just doing:
def my_func():
...
my_func = my_dec(my_func)
您的my_dec()
装饰者现在返回了一个元组(func, wrapper)
而不是包装函数,所以当您尝试拨打my_func()
时,您实际上正在尝试"呼叫& #34;已分配给my_func
的元组。
作为一个很好的衡量标准,您应该学习如何使用functools.wraps
,这是一个用于调用update_wrapper()
的便捷函数,它将包装函数更新为 FUNC :
from functools import wraps
def my_dec(func):
@wraps(func)
def wrapper():
decoration = "decorated"
print(decoration)
return func()
return wrapper
没有它,你得到:
In [4]: print(my_func.__name__)
wrapper
和包装:
In [9]: print(my_func.__name__)
my_func
它也会复制其他有用的属性,例如__doc__
。