簡體   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