如何用 `functools.lru_cache` 正确装饰`classmethod`?
Posted
技术标签:
【中文标题】如何用 `functools.lru_cache` 正确装饰`classmethod`?【英文标题】:How do I properly decorate a `classmethod` with `functools.lru_cache`? 【发布时间】:2020-02-27 04:16:15 【问题描述】:我尝试用functools.lru_cache
装饰classmethod
。我的尝试失败了:
import functools
class K:
@functools.lru_cache(maxsize=32)
@classmethod
def mthd(i, stryng: str): \
return stryng
obj = K()
错误信息来自functools.lru_cache
:
TypeError: the first argument must be callable
【问题讨论】:
classmethod
必须最后使用.. 这意味着它必须位于装饰器链的顶部
【参考方案1】:
类方法本身是不可调用的。 (是可调用的是类方法的__get__
方法返回的对象。)
因此,您希望将lru_cache
修饰的函数转换为类方法。
@classmethod
@functools.lru_cache(maxsize=32)
def mthd(cls, stryng: str):
return stryng
【讨论】:
【参考方案2】:所选答案完全正确,但要添加另一个帖子。如果您想将缓存存储绑定到每个类,而不是将单个存储共享给它的所有子类,还有另一个选项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')
那么结果就是
$ python example.py
functools 1
functools 2
methodtools 1
methodtools 2
functools 1
functools 2
【讨论】:
以上是关于如何用 `functools.lru_cache` 正确装饰`classmethod`?的主要内容,如果未能解决你的问题,请参考以下文章
将 functools.lru_cache 应用于 lambda
在 Python >= 3.2 中将缓存存储到文件 functools.lru_cache