Tengo algunas funciones computacionalmente intensivas en mi script de Python que me gustaría almacenar en caché. Busqué soluciones en el desbordamiento de pila y encontré muchos enlaces:
- /programming/4431703/python-resettable-instance-method-memoization-decorator
- https://wiki.python.org/moin/PythonDecoratorLibrary#Memoize
- http://pythonhosted.org/cachetools/
- https://pythonhosted.org/Flask-Cache/ (he usado este para aplicaciones de matraz, pero este no es un matraz).
Al final, terminé pegando esto en mi programa. Parece bastante simple, y funciona bien.
class memoized(object):
'''Decorator. Caches a function's return value each time it is called.
If called later with the same arguments, the cached value is returned
(not reevaluated).
'''
def __init__(self, func):
self.func = func
self.cache = {}
def __call__(self, *args):
if not isinstance(args, collections.Hashable):
return self.func(*args)
if args in self.cache:
return self.cache[args]
else:
value = self.func(*args)
self.cache[args] = value
return value
def __repr__(self):
'''Return the function's docstring.'''
return self.func.__doc__
def __get__(self, obj, objtype):
'''Support instance methods.'''
return functools.partial(self.__call__, obj)
Sin embargo, me pregunto si hay una mejor práctica canónica en Python. Supongo que supuse que habría un paquete muy utilizado para manejar esto y estoy confundido acerca de por qué esto no existe. http://pythonhosted.org/cachetools/ solo está en la versión .6 y la sintaxis es más compleja que simplemente agregar un decorador @memoize, como en otras soluciones.
@cached_property
decorador , que se adapta mejor a los métodos cuyos valores de retorno se mantendrán iguales durante toda la vida de la instancia.Debido a que un método de instancia puede usar atributos propios y, en particular, modificarlos, no puede garantizar la corrección de un método de instancia memorable arbitrario. Además, su implementación agrega una restricción implícita en su objeto para que sea hashable, y el acierto de caché dependiendo de ese hash, está limitado en las clases en las que puede usarlo y en los campos que puede agregar a las clases que tienen un método memorizado (o heredar uno).
Por estas razones, si necesita memorizar una función, es mejor diseñar convertir el método de instancia costoso en un método estático, pasándole explícitamente los atributos de objeto necesarios como argumentos. Esto libera tus manos en el diseño de clase y puede mejorar el éxito de la memoria caché. Esto también ayuda a simplificar y generalizar el código de memorización. Existen implementaciones de grano fino para este diseño, que a veces le permiten personalizar el tamaño de la memoria caché, la duración / métodos de invalidación, garantizando la seguridad del hilo, la persistencia ...
fuente