【问题标题】:Propagating arguments to decorator which combines other decorators将参数传播到结合了其他装饰器的装饰器
【发布时间】:2016-10-10 21:46:11
【问题描述】:

我有这样一个场景:

@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。

【问题讨论】:

    标签: python decorator python-decorators


    【解决方案1】:

    @decorator_one(1) 表示有一个返回装饰器的可调用对象;称它为装饰器工厂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(),但您也可以使用显式命名的参数。

    【讨论】:

      【解决方案2】:

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

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

      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
      

      【讨论】:

        猜你喜欢
        • 2016-05-03
        • 2020-02-10
        • 2021-11-21
        • 2012-03-20
        • 2014-11-17
        • 2013-03-10
        • 2021-09-14
        • 1970-01-01
        • 2011-06-25
        相关资源
        最近更新 更多