decorador de memoria de método de instancia reiniciable de Python
Estoy intentando construir un decorador para un método de instancia de una clase que memorizará el resultado. (Esto se ha hecho un millón de veces antes) Sin embargo, me gustaría la opción de poder restablecer la memoria caché memorizada en cualquier momento (por ejemplo, si algo en el estado de la instancia cambia, lo que podría cambiar el resultado de que el método no tenga nada que ver con sus args). Entonces, intenté construir un decorador como una clase en lugar de una función, para poder tener acceso al caché como miembro de la clase. Esto me llevó por el camino de aprender sobre descriptores, específicamente el__get__
método, que es donde realmente estoy atascado. Mi código se ve así:
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)
¿Es esto claro y / o posible? Cada vez__get__
se llama, obtengo una nueva instancia de la clase memorizada, que me pierde el caché con datos reales. He estado trabajando duro con__get__
, pero no estoy progresando mucho.
¿Existe un enfoque completamente separado para este problema que me falta por completo? Y todos los consejos / sugerencias son bienvenidos y apreciados. Gracias.