functools: lru_cache e cached_property
Memorizzi nella cache i calcoli costosi con lru_cache e cached_property.
functools: lru_cache e cached_property è una lezione Python Academy gratuita su CoddyKit. Questa è la lezione 4 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento Python Academy, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso Python Academy include 4 lezioni in totale.
Che cos'è la memoizzazione?
La memoizzazione memorizza nella cache il risultato di una chiamata di funzione, indicizzato in base ai suoi argomenti. Le chiamate ripetute con gli stessi argomenti restituiscono immediatamente il risultato memorizzato.
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) memorizza nella cache fino a maxsize risultati recenti. Imposti maxsize=None per una cache senza limite.
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 è una forma abbreviata di lru_cache(maxsize=None): una cache senza limite con un nome più semplice.
import functools
@functools.cache
def factorial(n):
return n * factorial(n-1) if n else 1
print(factorial(10)) # 3628800Informazioni e svuotamento della cache
Le funzioni con cache espongono .cache_info() (hit, miss e dimensione) e .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()Criterio di espulsione LRU
LRU (Least Recently Used, usato meno di recente) espelle l'elemento a cui si è avuto accesso meno recentemente quando la cache è piena.
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 argomenti hashable
lru_cache richiede che tutti gli argomenti siano hashable. Le liste e i dizionari non lo sono; utilizzi invece le tuple.
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 calcola una proprietà una volta e memorizza il risultato sull'istanza, sostituendo il descrittore con il valore.
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 o property
@property ricalcola il valore a ogni accesso. @cached_property lo calcola una volta e memorizza il risultato in 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))Sicurezza dei thread con cached_property
cached_property non è thread-safe. Se più thread vi accedono contemporaneamente, il calcolo può essere eseguito più di una volta. Utilizzi un lock se necessario.
import functools, threading
class SafeCache:
_lock = threading.Lock()
@functools.cached_property
def data(self):
with self._lock:
return expensive_computation()Invalidare cached_property
Elimini l'attributo dell'istanza per invalidare la cache e forzare il ricalcolo al successivo accesso.
import functools
class Report:
@functools.cached_property
def summary(self):
return compute_summary()
r = Report()
_ = r.summary # computed
del r.summary # invalidate
_ = r.summary # recomputedUsare lru_cache come cache API
Memorizzi nella cache le risposte API per tutta la durata di una sessione, così da evitare chiamate di rete ridondanti. Svuoti la cache quando servono dati aggiornati.
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) # cachedVerifica rapida
Quale metodo cancella tutti i risultati memorizzati nella cache di una funzione decorata con @lru_cache?
Riepilogo
@lru_cache memorizza nella cache i risultati delle funzioni indicizzati in base agli argomenti, che devono essere hashable. @cache è un alias senza limite. @cached_property memorizza nella cache il calcolo di una proprietà per ogni istanza. Esamini la cache con cache_info() e la reimposti con cache_clear().
Domande Frequenti
La lezione «functools: lru_cache e cached_property» è gratuita?
Sì — il testo completo di «functools: lru_cache e cached_property» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso Python Academy, passa a CoddyKit PRO. Il corso Python Academy include 4 lezioni in totale.
Cosa imparerò in «functools: lru_cache e cached_property»?
Memorizzi nella cache i calcoli costosi con lru_cache e cached_property. Eserciti Python Academy con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.
Ho bisogno di esperienza per iniziare Python Academy?
Non è richiesta alcuna esperienza precedente. Python Academy su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 4 di 4.
Quanto tempo richiede la lezione «functools: lru_cache e cached_property»?
La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.
Posso scrivere ed eseguire codice in questa lezione Python Academy?
Sì. Ogni lezione Python Academy include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.
Tutte le lezioni di questo corso
- itertools: iteratori infiniti e finiti
- itertools: calcolo combinatorio
- functools: partial e reduce
- functools: lru_cache e cached_property