传播装饰器的参数,它结合了其他装饰器

时间:2016-10-10 21:46:12

标签: python decorator python-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。

2 个答案:

答案 0 :(得分:4)

@decorator_one(1)表示有一个返回装饰器的callable;称之为装饰者工厂decorator_one(1)返回然后应用于函数的装饰器。

只需传递你自己的装饰工厂的参数:

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(),但您也可以使用显式命名的参数。

答案 1 :(得分:0)

是的,你需要装饰工厂。

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

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