У меня есть рабочий декоратор memoize, который использует кеш-память Django для запоминания результата функции в течение определенного промежутка времени. Я специально применяю это к методу класса.
Мой декоратор выглядит так:
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: индекс кортежа вне диапазона», указывающий на мою лямбда-функцию, как показано ранее.
Конечно, я могу успешно позвонить:
myStorageUnitInstance.someBigCalculation.invalidate(myStorageUnitInstance)
и это прекрасно работает. Но это "кажется" излишним, когда я уже ссылаюсь на конкретный экземпляр. Как я могу заставить Python рассматривать это как метод, привязанный к экземпляру, и, следовательно, правильно заполнять переменную "self"?