Acabo de comenzar Python y no tengo idea de qué es la memorización y cómo usarla. Además, ¿puedo tener un ejemplo simplificado?
python
memoization
blur959
fuente
fuente
Respuestas:
La memorización se refiere efectivamente a recordar ("memorización" → "memorando" → para ser recordado) los resultados de las llamadas a métodos basadas en las entradas del método y luego devolver el resultado recordado en lugar de calcular el resultado nuevamente. Puede pensarlo como un caché para los resultados del método. Para más detalles, consulte la página 387 para la definición en Introducción a los algoritmos (3e), Cormen et al.
Un ejemplo simple para calcular factoriales usando la memorización en Python sería algo como esto:
Puede volverse más complicado y encapsular el proceso de memorización en una clase:
Entonces:
Se agregó una característica conocida como " decoradores " en Python 2.4 que le permite ahora simplemente escribir lo siguiente para lograr lo mismo:
La biblioteca de decoradores de Python tiene un decorador similar llamado
memoized
que es ligeramente más robusto que laMemoize
clase que se muestra aquí.fuente
factorial_memo
, porque elfactorial
interiordef factorial
todavía llama a lo antiguo unmemoizefactorial
.if k not in factorial_memo:
, que se lee mejor queif not k in factorial_memo:
.args
es una tupla.def some_function(*args)
hace args una tupla.Nuevo en Python 3.2 es
functools.lru_cache
. Por defecto, sólo se almacena en caché los 128 llamadas utilizados más recientemente, pero se puede ajustar lamaxsize
aNone
para indicar que la caché nunca debe expirar:Esta función por sí sola es muy lenta, intente
fib(36)
y tendrá que esperar unos diez segundos.Agregar
lru_cache
anotaciones asegura que si la función ha sido llamada recientemente para un valor en particular, no volverá a calcular ese valor, sino que usará un resultado anterior en caché. En este caso, conduce a una mejora de velocidad tremenda, mientras que el código no está abarrotado con los detalles del almacenamiento en caché.fuente
fib
se llama, tendrá que volver al caso base antes de que pueda ocurrir la memorización. Entonces, su comportamiento es casi esperado.Las otras respuestas cubren lo que está bastante bien. No estoy repitiendo eso. Solo algunos puntos que pueden serle útiles.
Por lo general, la memorización es una operación que puede aplicar en cualquier función que calcule algo (costoso) y devuelva un valor. Debido a esto, a menudo se implementa como decorador . La implementación es sencilla y sería algo como esto
o expresado como decorador
fuente
Memoization es mantener los resultados de cálculos caros y devolver el resultado en caché en lugar de volver a calcularlo continuamente.
Aquí hay un ejemplo:
Se puede encontrar una descripción más completa en la entrada de wikipedia sobre memorización .
fuente
if input not in self.cache
yself.cache[input]
(has_key
es obsoleto desde ... al principio de la serie 2.x, si no 2.0.self.cache(index)
Nunca fue correcto. IIRC)No olvidemos la
hasattr
función incorporada, para aquellos que quieran hacer manualidades. De esa manera, puede mantener la memoria caché de mem dentro de la definición de la función (en lugar de una global).fuente
He encontrado esto extremadamente útil
fuente
functools.wraps
.memo
para que se libere la memoria?Básicamente, la memorización guarda los resultados de operaciones anteriores realizadas con algoritmos recursivos para reducir la necesidad de atravesar el árbol de recursión si se requiere el mismo cálculo en una etapa posterior.
ver http://scriptbucket.wordpress.com/2012/12/11/introduction-to-memoization/
Ejemplo de memorización de Fibonacci en Python:
fuente
La memorización es la conversión de funciones en estructuras de datos. Por lo general, uno quiere que la conversión se produzca de forma incremental y perezosa (a pedido de un elemento de dominio determinado, o "clave"). En lenguajes funcionales perezosos, esta conversión diferida puede ocurrir automáticamente y, por lo tanto, la memorización se puede implementar sin efectos secundarios (explícitos).
fuente
Bueno, primero debería responder la primera parte: ¿qué es la memorización?
Es solo un método para intercambiar memoria por tiempo. Piensa en la tabla de multiplicar .
Usar objetos mutables como valor predeterminado en Python generalmente se considera malo. Pero si lo usa sabiamente, en realidad puede ser útil implementar a
memoization
.Aquí hay un ejemplo adaptado de http://docs.python.org/2/faq/design.html#why-are-default-values-shared-between-objects
Usando un mutable
dict
en la definición de la función, los resultados computados intermedios pueden almacenarse en caché (por ejemplo, al calcularfactorial(10)
después de calcularfactorial(9)
, podemos reutilizar todos los resultados intermedios)fuente
Aquí hay una solución que funcionará con argumentos de tipo list o dict sin quejarse:
Tenga en cuenta que este enfoque puede extenderse naturalmente a cualquier objeto mediante la implementación de su propia función hash como un caso especial en handle_item. Por ejemplo, para hacer que este enfoque funcione para una función que toma un conjunto como argumento de entrada, puede agregar a handle_item:
fuente
list
argumento de[1, 2, 3]
puede considerarse erróneamente igual que unset
argumento diferente con un valor de{1, 2, 3}
. Además, los conjuntos están desordenados como diccionarios, por lo que también deberían serlosorted()
. También tenga en cuenta que un argumento de estructura de datos recursiva causaría un bucle infinito.list
s yset
s son "tupleized" en el mismo y por lo tanto no se pueden distinguir unos de otros. El código de ejemplo para agregar soporte parasets
descrito en su última actualización no evita que me temo. Esto se puede ver fácilmente pasando por separado[1,2,3]
y{1,2,3}
como un argumento para una función de prueba d "memorizar" y ver si se llama dos veces, como debería ser o no.list
sysdict
porque es posible quelist
a tenga exactamente lo mismo que resultó de llamarmake_tuple(sorted(x.items()))
a un diccionario. Una solución simple para ambos casos sería incluir eltype()
valor de la tupla generada. Puedo pensar en una forma aún más simple específicamente para manejarset
s, pero no generaliza.Solución que funciona con argumentos posicionales y de palabras clave independientemente del orden en que se pasaron los argumentos de palabras clave (usando inspect.getargspec ):
Pregunta similar: la identificación de funciones varargs equivalentes requiere memorización en Python
fuente
fuente
if n not in cache
lugar. usarcache.keys
crearía una lista innecesaria en python 2Solo quería agregar a las respuestas ya proporcionadas, la biblioteca decoradora de Python tiene algunas implementaciones simples pero útiles que también pueden memorizar "tipos no compartibles", a diferencia
functools.lru_cache
.fuente