decorador de memorização de método de instância reinicializável python
Estou tentando criar um decorador para um método de instância de uma classe que memorize o resultado. (Isso já foi feito um milhão de vezes). No entanto, eu gostaria da opção de redefinir o cache memorizado a qualquer momento (por exemplo, se algo no estado da instância mudar, o que pode alterar o resultado do método sem nada a ver com seus argumentos). Portanto, tentei criar um decorador como uma classe em vez de uma função, para que eu pudesse ter acesso ao cache como membro da classe. Isso me levou a aprender sobre descritores, especificamente o__get__
método, que é onde eu estou realmente preso. Meu código tem a seguinte aparência:
import time
class memoized(object):
def __init__(self, func):
self.func = func
self.cache = {}
def __call__(self, *args, **kwargs):
key = (self.func, args, frozenset(kwargs.iteritems()))
try:
return self.cache[key]
except KeyError:
self.cache[key] = self.func(*args, **kwargs)
return self.cache[key]
except TypeError:
# uncacheable, so just return calculated value without caching
return self.func(*args, **kwargs)
# self == instance of memoized
# obj == instance of my_class
# objtype == class object of __main__.my_class
def __get__(self, obj, objtype=None):
"""Support instance methods"""
if obj is None:
return self
# new_func is the bound method my_func of my_class instance
new_func = self.func.__get__(obj, objtype)
# instantiates a brand new class...this is not helping us, because it's a
# new class each time, which starts with a fresh cache
return self.__class__(new_func)
# new method that will allow me to reset the memoized cache
def reset(self):
print "IN RESET"
self.cache = {}
class my_class:
@memoized
def my_func(self, val):
print "in my_func"
time.sleep(2)
return val
c = my_class()
print "should take time"
print c.my_func(55)
print
print "should be instant"
print c.my_func(55)
print
c.my_func.reset()
print "should take time"
print c.my_func(55)
Isso é claro e / ou possível? Cada vez__get__
é chamado, recebo uma nova instância da classe memorizada, que me perde o cache com dados reais. Eu tenho trabalhado duro com__get__
, mas não estou fazendo muito progresso.
Existe uma abordagem completamente separada para esse problema que estou perdendo completamente? E todos os conselhos / sugestões são bem-vindos e apreciados. Obrigado.