I tried to decorate a classmethod
with functools.lru_cache
. My attempt failed:
import functools
class K:
@functools.lru_cache(maxsize=32)
@classmethod
def mthd(i, stryng: str): \
return stryng
obj = K()
The error message comes from functools.lru_cache
:
TypeError: the first argument must be callable
A class method is, itself, not callable. (What is callable is the object return by the class method's __get__
method.)
As such, you want the function decorated by lru_cache
to be turned into a class method instead.
@classmethod
@functools.lru_cache(maxsize=32)
def mthd(cls, stryng: str):
return stryng
The selected answer is totally correct but adding another post. If you want to bind the cache storages to each classes, instead of sharing the single storage to all its subclasses, there is another option methodtools
import functools
import methodtools
class K:
@classmethod
@functools.lru_cache(maxsize=1)
def mthd(cls, s: str):
print('functools', s)
return s
@methodtools.lru_cache(maxsize=1) # note that methodtools wraps classmethod
@classmethod
def mthd2(cls, s: str):
print('methodtools', s)
return s
class L(K):
pass
K.mthd('1')
L.mthd('2')
K.mthd2('1')
L.mthd2('2')
K.mthd('1') # functools share the storage
L.mthd('2')
K.mthd2('1') # methodtools doesn't share the storage
L.mthd2('2')
Then the result is
$ python example.py
functools 1
functools 2
methodtools 1
methodtools 2
functools 1
functools 2
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With