У меня есть рабочий memoize decorator, который использует backend сервера Django, чтобы запомнить результат функции на определенное количество времени. Я специально применяю это к методу класса.Декораторы и методы и методы класса Python - django memoize
Мой декоратора выглядит следующим образом:
def memoize(prefix='mysite', timeout=300, keygenfunc=None):
# MUST SPECIFY A KEYGENFUNC(args, kwargs) WHICH MUST RETURN A STRING
def funcwrap(meth):
def keymaker(*args, **kwargs):
key = prefix + '___' + meth.func_name + '___' + keygenfunc(args, kwargs)
return key
def invalidate(*args, **kwargs):
key = keymaker(*args, **kwargs)
cache.set(key, None, 1)
def newfunc(*args, **kwargs):
# construct key
key = keymaker(*args, **kwargs)
# is in cache?
rv = cache.get(key)
if rv is None:
# cache miss
rv = meth(*args, **kwargs)
cache.set(key, rv, timeout)
return rv
newfunc.invalidate = invalidate
return newfunc
return funcwrap
Я использую это на метод класса, так что-то вроде:
class StorageUnit(models.Model):
@memoize(timeout=60*180, keygenfunc=lambda x,y: str(x[0].id))
def someBigCalculation(self):
...
return result
Сам процесс запоминанием работает отлично! То есть, звонок в
myStorageUnitInstance.someBigCalculation()
должным образом использует кэш. Ладно, круто!
Моя проблема в том, когда я пытаюсь вручную аннулирует запись для конкретного экземпляра, где я хочу, чтобы иметь возможность запускать
myStorageUnitInstance.someBigCalculation.invalidate()
Однако, это не работает, потому что «я» не пройти, и поэтому ключ не получается. Я получаю ошибку IndexError: tuple index out of range, указывающую на мою функцию лямбда, как показано выше.
Конечно, я могу успешно назвать:
myStorageUnitInstance.someBigCalculation.invalidate(myStorageUnitInstance)
и это работает прекрасно. Но он «чувствует» избыточность, когда я уже ссылаюсь на конкретный экземпляр. Как я могу заставить Python рассматривать это как метод с привязкой к экземпляру и поэтому правильно заполнять переменную «self»?