Как правильно украсить `classmethod` с` functools.lru_cache`? - PullRequest
1 голос
/ 31 октября 2019

Я пытался украсить classmethod с functools.lru_cache. Моя попытка не удалась:

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

Ответы [ 2 ]

4 голосов
/ 31 октября 2019

Метод класса сам по себе не вызывается. (То, что означает , является вызываемым объектом, возвращаемым методом __get__ метода класса.)

Таким образом, вы хотите, чтобы функция, оформленная с помощью lru_cache, превратилась в метод класса. .

@classmethod
@functools.lru_cache(maxsize=32)
def mthd(cls, stryng: str):
    return stryng
0 голосов
/ 09 ноября 2019

Выбранный ответ является полностью правильным, но добавив еще один пост. Если вы хотите привязать кеш-хранилища к каждому классу, вместо того, чтобы делить одно хранилище со всеми его подклассами, есть другая опция 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
...