How do I properly decorate a `classmethod` with `functools.lru_cache`?
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
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