I am using cachetools for some basic caching. Here is an example of how I am using it:
class Access:
@cached(cache=TTLCache(maxsize=5, ttl=10))
def get_some_value(input: str):
# do some calls and return a value
The problem here is how do I make the maxsize
and ttl
configurable? I cannot do something like
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
I am looking for a way to inject those values if required and also have a default. Any helpful pointers? Also, get_some_value()
need not be an instance method. I could just make it a class method or module level also if need be.
To deal with this, we can use the fact that Python decorators are simply functions that return other functions.
Suppose you have this eggs
decorator:
def eggs(foo=10, bar=20):
def wrapper_gen(func):
def wrapper(*args):
print(foo, bar)
func(*args)
return wrapper
return wrapper_gen
And this Spam
class:
class Spam:
@eggs(foo=10, bar=20)
def baz(self, input):
print(input)
We can call the baz
method as such:
Spam().baz("Hello, world!")
And this gives us
10 20
Hello, world!
Now, instead of directly decorating the function, we'll decorate in our __init__
method:
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)
And now:
Spam(foo=20, bar=30).baz("Hello, world!")
This outputs
20 30
Hello, world!
The reason this works is that this:
@foo
def bar():
...
is shorthand for this:
def bar():
...
bar = foo(bar)
This can't work using the regular decorator syntax, for two reasons: get_some_value
belongs to the class, so it cannot have different behaviour for different instances since there's only one "copy" of it; and the decorator is executed at the time of the class declaration, not at the time of the instance creation, so there are no __init__
arguments yet.
However, you can get the result you want by applying the decorator explicitly in the __init__
method:
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):
...
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.