0Pricing
Python Academy · Lección

functools: lru_cache y cached_property

Almacene en caché cálculos costosos con lru_cache y cached_property.

functools: lru_cache y cached_property es una lección gratuita de Python Academy en CoddyKit. Esta es la lección 4 de 4. Puedes leer la lección completa abajo gratuitamente — luego la practicas en el navegador con un editor de código integrado y un tutor de IA 24/7. Forma parte de la ruta de aprendizaje de Python Academy, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de Python Academy incluye 4 lecciones en total.

¿Qué es la memoización?

La memoización almacena en caché el resultado de una llamada a una función, identificado por sus argumentos. Las llamadas repetidas con los mismos argumentos devuelven el resultado almacenado al instante.

def slow_fib(n):
    if n < 2: return n
    return slow_fib(n-1) + slow_fib(n-2)

# slow_fib(35) makes ~29 million calls
# With caching it makes only 35

@lru_cache

@functools.lru_cache(maxsize=128) almacena en caché hasta maxsize resultados recientes. Establezca maxsize=None para una caché sin límite.

import functools

@functools.lru_cache(maxsize=None)
def fib(n):
    if n < 2: return n
    return fib(n-1) + fib(n-2)

print(fib(50))  # instant

@cache — Python 3.9+

functools.cache es una forma abreviada de lru_cache(maxsize=None): una caché sin límite y con un nombre más claro.

import functools

@functools.cache
def factorial(n):
    return n * factorial(n-1) if n else 1

print(factorial(10))  # 3628800

Información y borrado de la caché

Las funciones con caché exponen .cache_info() (aciertos, fallos y tamaño) y .cache_clear().

import functools

@functools.lru_cache(maxsize=100)
def square(n):
    return n * n

for i in range(5): square(i % 3)
print(square.cache_info())
# CacheInfo(hits=2, misses=3, maxsize=100, currsize=3)
square.cache_clear()

Política de desalojo LRU

LRU (Least Recently Used, menos recientemente utilizado) desaloja el elemento al que se accedió hace más tiempo cuando la caché está llena.

import functools

@functools.lru_cache(maxsize=3)
def compute(n):
    print(f"computing {n}")
    return n**2

for x in [1,2,3,4,1]:   # 4 evicts 1 (LRU), then 1 re-computes
    compute(x)

Solo argumentos hashables

lru_cache requiere que todos los argumentos sean hashables. Las listas y los diccionarios no lo son; use tuplas en su lugar.

import functools

@functools.lru_cache(maxsize=None)
def sum_tuple(t):  # tuple is hashable
    return sum(t)

print(sum_tuple((1,2,3)))  # 6
# sum_tuple([1,2,3])  # TypeError

@cached_property

functools.cached_property calcula una propiedad una vez y almacena el resultado en la instancia, reemplazando el descriptor por el valor.

import functools

class Circle:
    def __init__(self, r):
        self.r = r

    @functools.cached_property
    def area(self):
        import math
        print("computing...")
        return math.pi * self.r ** 2

c = Circle(5)
print(c.area)   # computing...  78.53...
print(c.area)   # 78.53... (cached, no print)

cached_property frente a property

@property recalcula el valor en cada acceso. @cached_property lo calcula una vez y almacena el resultado en instance.__dict__.

import functools

class Expensive:
    @property
    def always(self):    # runs every access
        return sum(range(1_000_000))

    @functools.cached_property
    def once(self):      # runs only first access
        return sum(range(1_000_000))

Seguridad de subprocesos de cached_property

cached_property no es segura para subprocesos. Si varios subprocesos acceden a ella simultáneamente, el cálculo puede ejecutarse más de una vez. Use un bloqueo si es necesario.

import functools, threading

class SafeCache:
    _lock = threading.Lock()

    @functools.cached_property
    def data(self):
        with self._lock:
            return expensive_computation()

Invalidación de cached_property

Elimine el atributo de la instancia para invalidar la caché y forzar el recálculo en el siguiente acceso.

import functools

class Report:
    @functools.cached_property
    def summary(self):
        return compute_summary()

r = Report()
_ = r.summary      # computed
del r.summary      # invalidate
_ = r.summary      # recomputed

Uso de lru_cache como caché de API

Almacene en caché las respuestas de la API durante una sesión para evitar llamadas de red redundantes. Borre la caché cuando necesite datos actualizados.

import functools, urllib.request, json

@functools.lru_cache(maxsize=32)
def get_user(user_id):
    url = f"https://api.example.com/users/{user_id}"
    with urllib.request.urlopen(url) as r:
        return json.loads(r.read())

user = get_user(42)   # network call
user = get_user(42)   # cached

Comprobación rápida

¿Qué método borra todos los resultados almacenados en caché de una función decorada con @lru_cache?

Resumen

@lru_cache almacena en caché los resultados de una función identificados por sus argumentos (que deben ser hashables). @cache es un alias sin límite. @cached_property almacena en caché el cálculo de una propiedad por instancia. Consulte la información con cache_info() y restablezca la caché con cache_clear().

Preguntas frecuentes

¿La lección «functools: lru_cache y cached_property» es gratis?

Sí — el texto completo de «functools: lru_cache y cached_property» es gratis para leer aquí en la web. Para practicarla de forma interactiva (editor de código integrado y tutor de IA 24/7) y desbloquear el resto del curso de Python Academy, actualiza a CoddyKit PRO. El curso de Python Academy incluye 4 lecciones en total.

¿Qué aprenderé en «functools: lru_cache y cached_property»?

Almacene en caché cálculos costosos con lru_cache y cached_property. Practicas Python Academy con código real que ejecutas directamente en el navegador, y un tutor de IA 24/7 responde tus preguntas mientras trabajas en la lección.

¿Necesito experiencia previa para empezar Python Academy?

No se requiere experiencia previa. Python Academy en CoddyKit está estructurado para principiantes hasta estudiantes avanzados, así que puedes empezar aquí o desde el inicio y avanzar a tu ritmo. Esta es la lección 4 de 4.

¿Cuánto tiempo toma la lección «functools: lru_cache y cached_property»?

La mayoría de las lecciones de CoddyKit toman alrededor de 5–10 minutos. Cada una es compacta e interactiva, así que avanzas constantemente y retomas exactamente por donde dejaste en la web y la app.

¿Puedo escribir y ejecutar código en esta lección de Python Academy?

Sí. Cada lección de Python Academy incluye un editor de código integrado, así que escribes y ejecutas código real directamente en tu navegador y obtienes retroalimentación instantánea de IA — sin configuración local necesaria.

Todas las lecciones de este curso

  1. itertools: iteradores infinitos y finitos
  2. itertools: combinatoria
  3. functools: partial y reduce
  4. functools: lru_cache y cached_property
← Volver a Python Academy