Así es como puede memorizar una función de Python:
def memo_square(a, cache={}): if a not in cache: cache[a] = a*a return cache[a]
La recepción es inmerecidamente poco conocida, por lo que bajo el corte, analizaremos cómo funciona y para qué sirve.
Primero, cómo y por qué funciona.
memo_square
(como cualquier otra función) es un objeto de la clase de función, que, entre otros atributos, tiene una tupla
memo_square.__defaults__
completada al crear el objeto. Primero, contiene un diccionario vacío, como se indica en el encabezado de la función:
>>> memo_square.__defaults__ ({},)
__defaults__
es una tupla normal y no puede cambiar sus elementos. Es cierto que puede reemplazar todo el conjunto de valores predeterminados a la vez, pero solo por otra tupla:
>>> def test(a=1, b=2): ... print(a, b) ... >>> test.__defaults__ (1, 2) >>> test() 1 2 >>> test.__defaults__ = (', ', '') >>> test() , >>> test.__defaults__[1] = '' Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: 'tuple' object does not support item assignment >>> test.__defaults__ = {0: ', ', 1: ''} Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: __defaults__ must be set to a tuple object
Soryan, este artículo no llegará a Picaba. Bueno, está bien, esto no es importante. Lo importante es que, con la excepción del código muy astuto,
func.__defaults__
se crea una vez durante el tiempo del programa con todos sus elementos. Una tupla y sus elementos no se recrearán con cada llamada de función, se utilizarán mientras exista la función. Pero para cambiar, si los elementos mismos son mutables, nadie los prohíbe. La incapacidad para trabajar con tales elementos es
una de las formas más comunes de dispararse en la pitón . Pero en realidad guardar valores entre llamadas a funciones puede ser bastante útil. Después de varias llamadas,
memo_square.__defaults__
se verá así:
>>> memo_square(2) 4 >>> memo_square.__defaults__ ({2: 4},) >>> memo_square(5) 25 >>> memo_square.__defaults__ ({2: 4, 5: 25},) >>> memo_square(2) 4 >>> memo_square.__defaults__ ({2: 4, 5: 25},)
Si ya se ha llamado a la función para el mismo valor, entonces se calcula el valor y, en consecuencia, la memoria caché no se repone. Para el cuadrado, el beneficio es pequeño (estrictamente hablando, para el cuadrado, el beneficio es negativo, porque buscar en el diccionario es más costoso que multiplicar dos números), pero para funciones realmente costosas, la memorización / almacenamiento en caché puede ser útil. Por supuesto, puede proporcionarlo en Python de más de una manera. Aquí están las alternativas que tenemos:
Lo principal que pierde este método de memorización es que no es muy idiomático. Personalmente, cuando me topé con esta decisión por primera vez, pensé por un par de minutos sobre lo que estaba sucediendo aquí y por qué. Por otro lado, en estos dos minutos comencé a comprender un poco mejor cómo funciona Python y sus argumentos. Entonces, incluso si no utiliza los argumentos predeterminados (para la memorización o, por ejemplo, para
acelerar la resolución de nombres ), conocer esta técnica sigue siendo útil para cualquier nutricionista.