【发布时间】:2020-02-26 18:33:24
【问题描述】:
假设我有以下装饰器。 (重复一个函数n次)
def repeat(num_times=4):
def decorator_repeat(func):
@functools.wraps(func)
def wrapper_repeat(*args, **kwargs):
for _ in range(num_times):
value = func(*args, **kwargs)
return value
return wrapper_repeat
return decorator_repeat
现在,它确实有一个默认值4,但是,即使我想用默认值调用它,我仍然必须这样调用它
@repeat()
def my_function():
print("hello")
而不是
@repeat
def my_function():
print("hello")
现在,我可以将装饰器的定义更改为
def repeat(_func=None, *, num_times=2):
def decorator_repeat(func):
@functools.wraps(func)
def wrapper_repeat(*args, **kwargs):
for _ in range(num_times):
value = func(*args, **kwargs)
return value
return wrapper_repeat
if _func is None:
return decorator_repeat
else:
return decorator_repeat(_func)
如果我愿意,可以启用不带参数调用它的功能。
但是,这是否可以在不更改装饰器代码的情况下,而是通过定义另一个装饰器来实现?
即我想定义一个装饰器enable_direct,这样我就可以将@enable_direct 添加到我的装饰器定义中并具有相同的效果。 (即如下)
@enable_direct
def repeat(num_times=4):
def decorator_repeat(func):
@functools.wraps(func)
def wrapper_repeat(*args, **kwargs):
for _ in range(num_times):
value = func(*args, **kwargs)
return value
return wrapper_repeat
return decorator_repeat
注意:
我知道How to create a Python decorator that can be used either with or without parameters?中提到的解决方案
该问题中的定义具有不同的签名,如果重新开始,则可以遵循该模式。但是,假设我有 20-30 个这样的装饰器定义(3 级嵌套)。我希望所有这些都可以在没有括号的情况下被调用。
def repeat 语句没有函数参数。该问题中的函数有 2 级嵌套,而我的有 3 级嵌套。我想问是否可以在不更改函数定义的情况下使用这样的装饰器定义(应该用括号调用)。那里接受的答案有不同的签名,因此在这个问题中没有肉类要求。
注意 2: 在尝试那里给出的双包装定义之前,我没有问这个问题。不带括号调用它会返回另一个函数(如果函数的签名如所述)。
【问题讨论】:
-
这是一个略有不同的问题,但接受的答案确实回答了这个问题。
-
其中一个答案确实显示了一个装饰器被用作
@foo(不仅仅是@foo())和@foo(...)。 -
该问题中的定义具有不同的签名。在当前,
def repeat语句没有函数参数。该问题中的函数有 2 级嵌套,而我的有 3 级嵌套。我想问是否可以使用这样的装饰器定义(用括号调用)而不更改函数定义。那里接受的答案有不同的签名,因此在这个问题中不需要肉。 -
请看我修改后的答案
标签: python decorator python-decorators parentheses