python – 使用可选参数创建装饰器

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, ...):
上一篇:javascript – 覆盖jQuery函数 – 最佳实践


下一篇:python进阶一(函数式编程)【2-8 python中decorator装饰器】