ProgrammazioneSviluppatore Backend

Spiega come funzionano i decoratori in Python. Qual è il loro principale utilizzo, come vengono implementati e quali dettagli possono sorgere durante il loro utilizzo?

Supera i colloqui con l'assistente IA Hintsage

Risposta

I decoratori sono funzioni che prendono un'altra funzione e restituiscono una nuova funzione con comportamenti estesi o modificati. Vengono spesso utilizzati per registrazione, controllo dei diritti, caching, tempo di esecuzione e altro.

I decoratori vengono implementati utilizzando chiusure (closure) o classi che implementano il metodo __call__. La sintassi classica:

# Decoratore semplice def simple_decorator(func): def wrapper(*args, **kwargs): print("Prima della chiamata della funzione") result = func(*args, **kwargs) print("Dopo la chiamata della funzione") return result return wrapper @simple_decorator def my_func(): print("Funzione principale") my_func()

Il risultato sarà:

Prima della chiamata della funzione
Funzione principale
Dopo la chiamata della funzione

Il principale utilizzo — incapsulamento della logica ripetitiva al di fuori della logica di business principale.

Dettagli:

  • Senza l'uso di functools.wraps, si perde il nome della funzione originale e il suo docstring.
  • Se il decoratore accetta argomenti, si scrive una tripla annidamento di funzioni.

Domanda insidiosa

Domanda: "Se decoro una funzione con un decoratore e poi cerco di ottenere il nome della funzione tramite __name__, cosa vedrò e come preservare il nome originale?"

Risposta:

Per impostazione predefinita, il nome cambierà in quello del wrapper (di solito wrapper). Per preservare i metadati originali, utilizza functools.wraps:

import functools def dec(f): @functools.wraps(f) def wrapper(*args): return f(*args) return wrapper @dec def foo(): pass print(foo.__name__) # stamperà 'foo', non 'wrapper'

Esempi di errori reali a causa della mancanza di conoscenza dei dettagli dell'argomento


Storia

In una grande automazione delle risorse, dopo aver avvolto le funzioni con decoratori, il sistema di autotest è stato rotto, poiché utilizzava la riflessione sui nomi delle funzioni di test. Il problema era l'assenza di functools.wraps.


Storia

Un decoratore che aggiunge registrazione non supportava funzioni con firme diverse, poiché non venivano utilizzati *args, **kwargs. Alcune funzioni semplicemente si rompevano Silent Fail.


Storia

In un progetto con autorizzazione in REST API, un sviluppatore ha implementato un decoratore con parametri, ma ha dimenticato di annidare correttamente le funzioni (c'era un annidamento a due livelli invece di tre). Di conseguenza, il decoratore non poteva accettare parametri.