有人问了similar question,但是OP将包装器与没有返回值的函数进行了比较,因此答案集中在该“故障”上。
我了解装饰器,以及为什么在阅读this article之后使用装饰器而不是子类。在这里,他们编写了以下示例,其中介绍了包装器的需求:
def uppercase_decorator(function):
def wrapper():
funct = function()
make_uppercase = funct.upper()
return make_uppercase
return wrapper
但是,我可以这样写“同一件事”(我希望你说不是):
def uppercase_decorator(function): #previously 'function' was called 'message' but 'function' is clearer for comparison.
make_uppercase = function().upper
return make_uppercase
这两个版本都可以应用于此fn,从而在调用salute()
时产生相同的输出('HI ALL!'):
@uppercase_decorator
def salute():
return 'Hi all!'
如果main fn返回一个随机字符串(感谢@wim提出建议),则可以注意到每次运行它时,没有包装器的字符串总是在运行sayGarbage()
行时返回相同的内容:
def decorateIt(fn):
toUpper = fn().upper
return toUpper
def decorateW(fn):
def wrapper():
funct = fn()
toUpper = funct.upper()
return toUpper
return wrapper
import random, string
@decorateIt
def sayGarbage():
return "".join(random.choice(string.ascii_lowercase) for i in range(6))
sayGarbage()
为什么会这样?
答案 0 :(得分:3)
让我们看看这里发生了什么:
def uppercase_decorator(message):
make_uppercase = func().upper
return make_uppercase
@uppercase_decorator
def salute():
return 'Hi all!'
uppercase_decorator
。salute
被定义。uppercase_decorator
被称为 ,将函数对象salute
替换为第一个位置参数(message
)。在这一点上,代码将崩溃,因为func()
被调用并且未在任何地方定义。如果它在您的Python REPL会话中有效,那么您必须早早在全局范围内使用func
这个名称,因此该代码似乎只是巧合地起作用。
我们真的需要装饰器包装器吗?
不。可以按照您的建议,以更好的“无封闭”样式编写装饰器,但并非如此。如果要编写不带嵌套函数的装饰器,请尝试使用流行的库decorator.py
来尝试。看起来像这样:
from decorator import decorator
@decorator
def uppercase_decorator(func, *args, **kwargs):
result = func(*args, **kwargs)
return result.upper()