繁体   English   中英

如何使python装饰器中的参数可配置?

[英]How to make arguments in python decorator configurable?

我正在使用cachetools进行一些基本的缓存。 这是我如何使用它的示例:

class Access:

  @cached(cache=TTLCache(maxsize=5, ttl=10))
  def get_some_value(input: str):
    # do some calls and return a value

这里的问题是如何使maxsizettl配置? 我不能做类似的事情

class Access:
  def __init__(self, maxsize: int = 5, ttl: int = 10):
    self.maxsize = maxsize
    self.ttl = ttl

  @cached(cache=TTLCache(maxsize=self.maxsize, ttl=self.ttl))
  def get_some_value(input: str):
    # do some calls and return a value

如果需要,我正在寻找一种方法来注入这些值,并且还有一个默认值。 任何有用的指针? 此外, get_some_value()不必是实例方法。 如果需要,我也可以将其设为类方法或模块级别。

为了解决这个问题,我们可以利用 Python 装饰器只是返回其他函数的函数这一事实。

假设你有这个eggs装饰器:

def eggs(foo=10, bar=20):
    def wrapper_gen(func):
        def wrapper(*args):
            print(foo, bar)
            func(*args)
        return wrapper
    return wrapper_gen

这个Spam类:

class Spam:
    @eggs(foo=10, bar=20)
    def baz(self, input):
        print(input)

我们可以这样调用baz方法:

Spam().baz("Hello, world!")

这给了我们

10 20
Hello, world!

现在,我们将在__init__方法中进行装饰,而不是直接装饰函数:

class Spam:
    def __init__(self, foo=10, bar=20):
        self.baz = eggs(foo=foo, bar=bar)(self._baz_func)

    def _baz_func(self, input):
        print(input)

现在:

Spam(foo=20, bar=30).baz("Hello, world!")

这输出

20 30
Hello, world!

这样做的原因是:

@foo
def bar():
    ...

是这个的简写:

def bar():
    ...

bar = foo(bar)

这不能使用常规装饰器语法工作,原因有两个: get_some_value属于该类,因此对于不同的实例它不能有不同的行为,因为它只有一个“副本”; 并且装饰器在类声明时执行,而不是在实例创建时执行,因此还没有__init__参数。

但是,您可以通过在__init__方法中显式应用装饰器来获得所需的结果:

class Access:
    def __init__(self, maxsize: int = 5, ttl: int = 10):
        decorator = cached(cache=TTLCache(maxsize=maxsize, ttl=ttl))
        self.get_some_value = decorator(self.get_some_value)

    def get_some_value(self, input: str):
        ...

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM