__CODE__
使用带括号或不带括号的相同装饰器有什么区别?例如:
没有括号
@some_decorator
def some_method():
pass
Run Code Online (Sandbox Code Playgroud)
括号
@some_decorator()
def some_method():
pass
Run Code Online (Sandbox Code Playgroud)
vau*_*tah 51
some_decorator
在第一个代码片段中是一个常规装饰器:
@some_decorator
def some_method():
pass
Run Code Online (Sandbox Code Playgroud)
相当于
some_method = some_decorator(some_method)
Run Code Online (Sandbox Code Playgroud)
另一方面,some_decorator
在第二个代码片段中是一个返回装饰器的可调用代码:
@some_decorator()
def some_method():
pass
Run Code Online (Sandbox Code Playgroud)
相当于
some_method = some_decorator()(some_method)
Run Code Online (Sandbox Code Playgroud)
正如Duncan在评论中指出的那样,一些装饰器被设计为双向工作.这是这种装饰器的一个非常基本的实现:
def some_decorator(arg=None):
def decorator(func):
def wrapper(*a, **ka):
return func(*a, **ka)
return wrapper
if callable(arg):
return decorator(arg) # return 'wrapper'
else:
return decorator # ... or 'decorator'
Run Code Online (Sandbox Code Playgroud)
pytest.fixture
是一个更复杂的例子.
简而言之,装饰器允许向一组函数和类添加丰富的特性,而无需对其进行任何修改。
关键要了解的差值之间@some_decorator
以及@some_decorator()
在于前者是装饰,而后者是一个函数(或可调用)返回一个装饰。
我相信看到每个案例的实现有助于理解差异:
@some_decorator
def some_decorator(func):
def wrapper(func):
return func(*args, **kwargs)
return wrapper
Run Code Online (Sandbox Code Playgroud)
应用:
@some_decorator
def some_method():
pass
Run Code Online (Sandbox Code Playgroud)
等价:
some_method = some_decorator(some_method)
Run Code Online (Sandbox Code Playgroud)
@some_decorator()
def some_decorator():
def decorator(func):
def wrapper(*args, **kwargs):
return func(*args, **kwargs)
return wrapper
return decorator
Run Code Online (Sandbox Code Playgroud)
应用:
@some_decorator()
def some_method():
pass
Run Code Online (Sandbox Code Playgroud)
等价:
some_method = some_decorator()(some_method)
Run Code Online (Sandbox Code Playgroud)
请注意,现在更容易看出这@some_decorator()
是一个返回装饰器的函数,而some_decorator
它只是一个装饰器。请记住,一些装饰器被编写为双向工作。
所以现在你可能想知道为什么我们有这两种情况,而前一个版本看起来更简单。答案是,如果您想将参数传递给装饰器, using@some_decorator()
将允许您这样做。让我们看看一些运行中的代码:
def some_decorator(arg1, arg2):
def decorator(func):
def wrapper(*args, **kwargs):
print(arg1)
print(arg2)
return func(*args, **kwargs)
return wrapper
return decorator
Run Code Online (Sandbox Code Playgroud)
应用:
@some_decorator('hello', 'bye')
def some_method():
pass
Run Code Online (Sandbox Code Playgroud)
等价:
some_method = some_decorator('hello', 'bye')(some_method)
Run Code Online (Sandbox Code Playgroud)
注意:我认为值得一提的是,装饰器可以实现为函数或类。检查这个以获取更多信息。