La memoización se refiere a recordar los resultados de las llamadas a un método de python (“memoización”, “memorándum” a recordar) con el fin de devolver el resultado y tener que perder el tiempo calculando de nuevo. Es muy útil en métodos recursivos, ya que evitan recursiones largas y con gran consumo de tiempo y recursos de la computadora. Se considerarlo como un caché para los resultados del método o función.

Veamos el siguente algoritmo para calcular números de Fibonacci:

 fibonacci(n):
    if n == 1:
          return 1
    elif n == 2:
          return 1
    elif n>2:
          return fibonacci(n-1) + fibonacci(n-2)

Este código es simple, elegante pero muy ineficiente en la medida de que n crezca mucho.

La mejor manera, usando esta técnica sería:

fibonacci_cache = {}
def fibonacci(n):
# vemos si ya conocemos el resultado y lo devolvemos, ya que debería haber quedado en el diccionario.
   if n in fibonacci_cache:
      return fibonacci_cache[n]
   if n == 1:
      return 1
   elif n == 2:
      return 1
   elif n>2:
      value = fibonacci(n-1) + fibonacci(n-2)
# guardo el valor en la cache
   fibonacci_cache[n] = value
   return value

La otra manera de resolver esto es con una librería que hace el trabajo, esta es la librería lru (Least Recently Used cache), aunque hay otros métodos para realizar la memoización.

@lru_cache(maxsize = 1000)
def fibonacci(n):
   if n == 1:
      return 1
   elif n == 2:
      return 1
   elif n>2:
      return fibonacci(n-1) + fibonacci(n-2)

El maxsize tiene si no se indica en default seteado en 128, pero siempre es mejor cachear con más memoria.

Para el caso de un calcular factoriales, en por ejemplo, una serie de Taylor, este proceso de evitar hacer cuantas de más sería realmente útil. La versión simple podría calcularse como:

factorial_memo = {}
def factorial(k):
    if k < 2: return 1
    if k not in factorial_memo:
        factorial_memo[k] = k * factorial(k-1)
    return factorial_memo[k]