Python « : » decoratori per misurare il tempo », ritentare, memorizzare in cache e validare

Python ":" decoratori per misurare il tempo », ritentare, memorizzare in cache e validare
3 min di lettura

I decoratori Python permettono di aggiungere a una funzione comportamenti comuni, come la misurazione della durata, i nuovi tentativi, la memorizzazione in cache o la validazione degli argomenti, senza modificarne il codice interno. In un tutorial pubblicato su Machine Learning Mastery, l’autore ne dettaglia il funzionamento e mostra come costruirne di affidabili, senza nascondere le eccezioni.

  • I decoratori Python aggiungono comportamenti comuni alle funzioni senza modificarne il codice interno.
  • Il wrapper usa functools.wraps per conservare nome e documentazione della funzione originale.
  • I nuovi tentativi sono sicuri solo per chiamate ripetibili senza conseguenze, come i pagamenti non lo sono.
  • Un decoratore non deve decidere la logica di business, che va collocata nella funzione o in un modello di dati.

Il punto di partenza è un modulo di elaborazione dati composto da tre funzioni che, nel corso delle settimane, si sono caricate di compiti accessori. Secondo il tutorial, una funzione verifica che il suo percorso esista prima di caricare gli embedding, un’altra ripete le sue richieste in un ciclo con time.sleep(), e la terza misura il suo tempo di esecuzione e conserva i risultati in un dizionario. Questo codice periferico, aggiunto manualmente, varia da una funzione all’altra, e ogni nuova funzione rischia di introdurne una variante.

Un decoratore, una semplice assegnazione

Il decoratore è una funzione che prende una funzione come argomento e restituisce un wrapper, cioè un involucro che esegue del codice prima e dopo la chiamata originale. Il tutorial ricorda che la sintassi @ equivale a una riassegnazione del nome della funzione, ciò che il glossario Python chiama zucchero sintattico. Il decoratore viene quindi eseguito una sola volta, al momento della definizione della funzione.

Il wrapper conserva la funzione originale grazie a una chiusura (closure), meccanismo per cui una funzione interna mantiene accesso alle variabili della funzione che la racchiude. I parametri *args e **kwargs trasmettono gli argomenti, e il risultato viene restituito così com’è. Senza ulteriori precauzioni, tuttavia, il wrapper sostituisce il nome e la documentazione della funzione. Il tutorial raccomanda quindi di usare functools.wraps, che copia questi metadati, così come l’attributo __wrapped__, che permette di accedere alla funzione non decorata durante i test.

Quattro comportamenti periferici

Il decoratore di misurazione si basa su time.perf_counter(), un orologio che serve a calcolare durate e non date. Collocato in un blocco try/finally, mostra la durata anche quando la funzione fallisce, l’eccezione rimanendo trasmessa al chiamante.

Il decoratore di nuovi tentativi è una fabbrica, che accetta opzioni come max_attempts, delay e le eccezioni da riprovare. Ritenta solo le eccezioni configurate, affinché un errore di programmazione non venga trattato come un problema di rete. All’ultimo tentativo, un raise nudo rilancia l’eccezione originale. Il tutorial sottolinea tuttavia un limite: questo approccio è sicuro solo per le chiamate che possono essere eseguite due volte senza conseguenze. Un pagamento o un invio di messaggio non rispondono a questo criterio.

Per la memorizzazione in cache, il tutorial raccomanda functools.lru_cache, che conserva i risultati delle chiamate più recenti, entro il limite di maxsize (ad esempio 256). I suoi vincoli dipendono dalla sua implementazione: gli argomenti devono essere hashable, e una funzione che restituisce un oggetto modificabile può produrre effetti inattesi. La validazione, infine, usa inspect.signature() per associare gli argomenti ai nomi dei parametri, anche quando sono passati per posizione o con il loro valore predefinito, poi applica regole semplici prima della chiamata.

Il tutorial si conclude con una regola di prudenza: un decoratore non deve decidere la logica di business della funzione. Quando il comportamento dipende dai dati, è meglio collocarlo nella funzione, o in un modello di dati per la validazione. Quando più decoratori sono impilati, il loro ordine di applicazione conta, perché quello più in alto è il wrapper più esterno.

S’abonner
Notification pour
guest

0 Commentaires
Le plus ancien
Le plus récent Le plus populaire
0
Nous aimerions avoir votre avis, veuillez laisser un commentaire.x