from functools import wraps
def foo_register(method_name=None):
"""Does stuff."""
def decorator(method):
if method_name is None:
method.gw_method = method.__name__
else:
method.gw_method = method_name
@wraps(method)
def wrapper(*args, **kwargs):
method(*args, **kwargs)
return wrapper
return decorator
示例:下面用foo_register
来装饰my_function
,而不是将其改为decorator
。
@foo_register
def my_function():
print('hi...')
示例:以下操作如预期所示。
@foo_register('say_hi')
def my_function():
print('hi...')
如果我想让它在两个应用程序中都能正常工作(一个使用method.__name__
,另一个传入名称),我必须检查foo_register
的内部,看看第一个参数是否是decorator,如果是,我必须:return decorator(method_name)
(而不是return decorator
)。这种“检查一下是不是可以打电话”的说法似乎很老套。有没有更好的方法来创建这样一个多用途的decorator?
我已经知道我可以要求调用decorator,但这不是一个“解决方案”。我希望API感觉自然。我妻子喜欢装饰,我不想破坏它。
格伦-那时候我必须这么做。我想我很高兴没有“魔法”的方法来做这件事。我讨厌那些。
所以,这里是我自己的答案(方法名与上面不同,但概念相同):
示例用法(两个版本的工作原理相同):
通过这里和其他地方的答案的帮助和一系列的尝试和错误,我发现实际上有一种更简单和通用的方法可以让decorator接受可选参数。它确实检查了用它调用的args,但没有其他方法可以这样做。
关键是要装饰你的装饰师。
泛型decorator decorator代码
这里是decorator decorator(此代码是通用的,任何需要可选arg decorator的人都可以使用):
用法
使用它就像:
optional_arg_decorator
装饰装饰器示例:
测试用例
对于您的用例:
因此,对于您的情况,使用传入的方法名或
__name__
(如果None)保存函数的属性:添加修饰方法
现在您有了一个带或不带参数的装饰器:
我所知道的最干净的方法是:
说明
当调用decorator时没有如下可选参数:
函数作为第一个参数传递,decorate将按预期返回decorated函数。
如果使用一个或多个可选参数调用decorator,如下所示:
然后使用值为None的函数参数调用decorator,这样会返回一个decorate函数,如预期的那样。
Python 3
注意,上面的decorator签名可以使用Python 3特定的
*,
语法进行改进,以强制安全地使用关键字参数。只需将最外层函数的签名替换为:相关问题 更多 >
编程相关推荐