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,而不是将其设置为装饰器.
@foo_register
def my_function():
print('hi...')
示例:以下按预期工作.
@foo_register('say_hi')
def my_function():
print('hi...')
如果我希望它在两个应用程序中正常工作(一个使用方法.__ name__和一个传递名称),我必须检查foo_register内部以查看第一个参数是否是装饰器,如果是,我必须:返回decorator(method_name)(而不是返回装饰器).这种“检查它是否可以调用”似乎非常hackish.有没有更好的方法来创建这样的多用途装饰器?
附:我已经知道我可以要求调用装饰器,但这不是一个“解决方案”.我希望API感觉自然.我的妻子喜欢装饰,我不想破坏它.
解决方法:
我知道这样做最干净的方法如下:
import functools
def decorator(original_function=None, optional_argument1=None, optional_argument2=None, ...):
def _decorate(function):
@functools.wraps(function)
def wrapped_function(*args, **kwargs):
...
return wrapped_function
if original_function:
return _decorate(original_function)
return _decorate
说明
调用装饰器时没有像这样的可选参数:
@decorator
def function ...
函数作为第一个参数传递,decorate按预期返回修饰函数.
如果使用一个或多个可选参数调用装饰器,如下所示:
@decorator(optional_argument1='some value')
def function ....
然后使用值为None的函数参数调用装饰器,因此返回装饰的函数,如预期的那样.
Python 3
请注意,上面的装饰器签名可以使用Python 3特定的*语法进行改进,以强制安全使用关键字参数.只需将最外层函数的签名替换为:
def decorator(original_function=None, *, optional_argument1=None, optional_argument2=None, ...):