Considera lo siguiente:
@property
def name(self):
if not hasattr(self, '_name'):
# expensive calculation
self._name = 1 + 1
return self._name
Soy nuevo, pero creo que el almacenamiento en caché se puede descomponer en un decorador. Solo que no encontré uno igual;)
PD: el cálculo real no depende de valores mutables
python
caching
decorator
memoization
Tobias
fuente
fuente
Respuestas:
A partir de Python 3.2 hay un decorador incorporado:
@functools.lru_cache(maxsize=100, typed=False)
Ejemplo de un caché LRU para calcular números de Fibonacci :
Si está atascado con Python 2.x, aquí hay una lista de otras bibliotecas de memorización compatibles:
functools32
El | PyPI | Código fuenterepoze.lru
El | PyPI | Código fuentepylru
El | PyPI | Código fuentebackports.functools_lru_cache
El | PyPI | Código fuentefuente
lru_cache
hacer una copia de cualquier resultado que esté almacenando en caché, y no se está realizando dicha copia en lafunctools.lru_cache
implementación. Si lo hace, también correría el riesgo de crear problemas de memoria difíciles de encontrar cuando se usa para almacenar en caché un objeto grande.Parece que no está pidiendo un decorador de memorización de propósito general (es decir, no está interesado en el caso general en el que desea almacenar en caché los valores de retorno para diferentes valores de argumento). Es decir, te gustaría tener esto:
mientras que un decorador de memorización de uso general le daría esto:
Sostengo que la sintaxis de llamada al método es mejor estilo, porque sugiere la posibilidad de un cálculo costoso, mientras que la sintaxis de propiedad sugiere una búsqueda rápida.
[Actualización: el decorador de memoria basado en clases al que me había vinculado y citado aquí anteriormente no funciona para los métodos. Lo he reemplazado con una función de decorador.] Si está dispuesto a usar un decorador de memorización de propósito general, aquí hay uno simple:
Ejemplo de uso:
Otra decorador memoization con un límite en el tamaño de caché se puede encontrar aquí .
fuente
fibonacci
. Esa función siempre usa el mismomemo
diccionario.Usos de muestra:
fuente
functools.cached_property
Decorador Python 3.8https://docs.python.org/dev/library/functools.html#functools.cached_property
cached_property
de Werkzeug se mencionó en: https://stackoverflow.com/a/5295190/895245 pero una versión supuestamente derivada se fusionará con 3.8, lo cual es increíble.Este decorador puede verse como almacenamiento en caché
@property
, o como un limpiador@functools.lru_cache
para cuando no tienes ningún argumento.Los documentos dicen:
fuente
Werkzeug tiene un
cached_property
decorador ( documentos , fuente )fuente
Codifiqué esta clase de decorador simple para almacenar en caché las respuestas de la función. Lo encuentro MUY útil para mis proyectos:
El uso es sencillo:
fuente
@cached
le faltan paréntesis. De lo contrario sólo se devolverá elcached
objeto en lugar demyfunc
y cuando se le llama comomyfunc()
a continuacióninner
siempre que se obtiene es un valor de retornoDESCARGO DE RESPONSABILIDAD: Soy el autor de kids.cache .
Debe verificar
kids.cache
, proporciona un@cache
decorador que funciona en python 2 y python 3. Sin dependencias, ~ 100 líneas de código. Es muy sencillo de usar, por ejemplo, teniendo en cuenta su código, puede usarlo así:Luego
O podría poner el
@cache
decorador después del@property
(mismo resultado).Usar caché en una propiedad se llama evaluación perezosa ,
kids.cache
puede hacer mucho más (funciona en función con cualquier argumento, propiedades, cualquier tipo de método e incluso clases ...). Para usuarios avanzados,kids.cache
soportecachetools
que proporciona almacenes de caché elegantes para python 2 y python 3 (caché LRU, LFU, TTL, RR).NOTA IMPORTANTE : el almacén de caché predeterminado
kids.cache
es un dict estándar, que no se recomienda para programas de larga ejecución con consultas siempre diferentes, ya que conduciría a un almacén de almacenamiento en caché cada vez mayor. Para este uso, puede agregar otros almacenes de caché, por ejemplo (@cache(use=cachetools.LRUCache(maxsize=2))
para decorar su función / propiedad / clase / método ...)fuente
c
deMyClass
, e inspeccionar conobjgraph.show_backrefs([c], max_depth=10)
, hay una cadena ref de la clase de objetoMyClass
ac
. Es decir,c
nunca se lanzaría hasta que seMyClass
haya lanzado.Ah, solo necesitaba encontrar el nombre correcto para esto: " Evaluación de propiedad perezosa ".
Yo también hago esto mucho; quizás alguna vez use esa receta en mi código.
fuente
Hay fastcache , que es "Implementación en C de Python 3 functools.lru_cache. Proporciona una velocidad de 10-30x sobre la biblioteca estándar".
Igual que la respuesta elegida , solo diferente importación:
Además, viene instalado en Anaconda , a diferencia de las functools que deben instalarse .
fuente
functools
es parte de la biblioteca estándar, el enlace que ha publicado es un tenedor aleatorio de git o algo más ...Hay otro ejemplo de un decorador de memoria en Python Wiki:
http://wiki.python.org/moin/PythonDecoratorLibrary#Memoize
Ese ejemplo es un poco inteligente, porque no almacenará en caché los resultados si los parámetros son mutables. (verifique ese código, ¡es muy simple e interesante!)
fuente
Si está utilizando Django Framework, tiene dicha propiedad para almacenar en caché una vista o respuesta de API utilizando
@cache_page(time)
y también puede haber otras opciones.Ejemplo:
Más detalles se pueden encontrar aquí .
fuente
Junto con el ejemplo de Memoize encontré los siguientes paquetes de python:
fuente
Implementé algo como esto, usando pickle para persistencia y usando sha1 para identificaciones cortas casi ciertamente únicas. Básicamente, la memoria caché codificó el código de la función y el historial de argumentos para obtener un sha1 y luego buscó un archivo con ese sha1 en el nombre. Si existió, lo abrió y devolvió el resultado; si no, llama a la función y guarda el resultado (opcionalmente solo guarda si se procesó una cierta cantidad de tiempo).
Dicho esto, juro que encontré un módulo existente que hizo esto y me encontré aquí tratando de encontrar ese módulo ... Lo más cerca que puedo encontrar es esto, que se ve a la derecha: http: //chase-seibert.github. io / blog / 2011/11/23 / pythondjango-disk-based-caching-decorator.html
El único problema que veo con eso es que no funcionaría bien para entradas grandes, ya que tiene hash str (arg), que no es exclusivo para matrices gigantes.
Sería bueno si hubiera un protocolo unique_hash () que hiciera que una clase devolviera un hash seguro de su contenido. Básicamente lo implementé manualmente para los tipos que me importaban.
fuente
Pruebe joblib http://pythonhosted.org/joblib/memory.html
fuente
Si está utilizando Django y desea almacenar en caché las vistas, consulte la respuesta de Nikhil Kumar .
Pero si desea almacenar en caché los resultados de CUALQUIER función, puede usar django-cache-utils .
Reutiliza cachés de Django y proporciona un
cached
decorador fácil de usar :fuente
@lru_cache
no es perfecto con valores de función predeterminadosmi
mem
decorador:y código para probar:
resultado: solo 3 veces con el sueño
pero con
@lru_cache
eso será 4 veces, porque esto:se calculará dos veces (mal funcionamiento con valores predeterminados)
fuente