将参数传播给结合其他装饰器的装饰器

Propagating arguments to decorator which combines other decorators

我有这样一个场景:

@decorator_one(1)
@foo
@bar
def my_decorated_func():
    pass

我正在尝试将其压缩成如下内容:

@my_custom_decorator(1)
def my_decorated_func():
    pass

如果我有没有 (1) 选项的装饰器,这很简单:

def my_custom_decorator(f):
    @decorator_one
    @foo
    @bar
    def wrapped():
        pass
    return wrapped

但是我不确定如何将参数正确传播到第一个包装器。

在这种情况下,我很乐意假设如果我将 1 传递给 my_custom_decorator,它将始终且仅作为 decorator_one 的 arg。

@decorator_one(1) 表示有一个 returns 装饰器的可调用对象;称它为装饰器 factorydecorator_one(1) returns 然后应用于函数的装饰器。

只需传递来自您自己的装饰器工厂的参数:

def my_custom_decorator(*args, **kwargs):  # the factory
    def decorator(f):                      # the decorator
        @decorator_one(*args, **kwargs)
        @foo
        @bar
        def wrapped():
            pass
        return wrapped
    return decorator

我使用 *args, **kwargs 将任意参数传递给包装装饰器工厂 decorator_one(),但您也可以使用明确命名的参数。

是的,你需要一个装饰器工厂。

我发现使用 class 的解决方案更有吸引力,因为它将工厂和装饰器分开:

class my_custom_decorator(object):

    __init__(self, *args, **kwargs):  # the factory
        self.args = args
        self.kwargs = kwargs

    __call__(self, f):  # the decorator
        @decorator_one(*self.args, **self.kwargs)
        @foo
        @bar
        def wrapped():
            pass

        return wrapped