如何使用 `functools.lru_cache` 正确装饰 `classmethod`?

How do I properly decorate a `classmethod` with `functools.lru_cache`?

我试着用 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

class 方法本身是不可调用的。 (可调用的是class方法的__get__方法的对象return。)

因此,您希望将 lru_cache 修饰的函数转换为 class 方法。

@classmethod
@functools.lru_cache(maxsize=32)
def mthd(cls, stryng: str):
    return stryng

所选答案完全正确,但要添加另一个 post。如果你想将缓存存储绑定到每个 类,而不是将单个存储共享给它的所有子 类,还有另一个选项 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