Come creare e utilizzare i decoratori in Python
Scopri come scrivere e applicare decoratori in Python. Padroneggiare le funzioni di wrapper, modificare il comportamento, gestire gli argomenti e preservare i metadati con i wrapper.
Panoramica
I decoratori sono una delle funzionalità di sintassi più eleganti e potenti di Python, consentendo di modificare il comportamento di una funzione o di una classe senza modificarne permanentemente il codice. Sono ampiamente utilizzati per questioni trasversali come la registrazione dei tempi di esecuzione, l'applicazione dell'autenticazione dell'utente, la memorizzazione nella cache dei risultati (memoizzazione) e il controllo degli endpoint API.
Dietro le quinte, un decoratore è una funzione di ordine superiore che accetta un'altra funzione come argomento, definisce una funzione wrapper nidificata che inserisce una logica personalizzata e restituisce questa funzione wrapper. Python fornisce una sintassi abbreviata pulita utilizzando il simbolo `@` per applicare decoratori alle funzioni, rendendole visivamente eleganti.
Quando si scrivono decoratori, in genere si desidera che la funzione decorata supporti un numero qualsiasi di argomenti posizionali e di parole chiave. Puoi ottenere questo risultato progettando la funzione wrapper nidificata in modo che accetti "*args" e "**kwargs" e li passi alla funzione di destinazione. Inoltre, dovresti utilizzare `functools.wraps` sulla funzione wrapper per preservare la docstring della funzione originale e i metadati del nome.
Codice e output di esecuzione
Questo script dimostra la scrittura di un decoratore di registrazione e il confezionamento di una funzione per controllare input, output e metadati.
from functools import wraps
# 1. Defining a decorator
def log_execution(func):
@wraps(func) # Preserves original function metadata
def wrapper(*args, **kwargs):
print(f"[Log] Calling function: {func.__name__} with args: {args}")
result = func(*args, **kwargs)
print(f"[Log] Finished {func.__name__}. Result: {result}")
return result
return wrapper
# 2. Applying the decorator using @ syntax
@log_execution
def add_numbers(a, b):
"""Adds two numbers and returns the sum."""
return a + b
# 3. Invoking the decorated function
sum_result = add_numbers(15, 25)
print("Sum Result:", sum_result)
# Verifying metadata preservation
print("Docstring preserved:", add_numbers.__doc__)[Log] Calling function: add_numbers with args: (15, 25)
[Log] Finished add_numbers. Result: 40
Sum Result: 40
Docstring preserved: Adds two numbers and returns the sum.Implementazione passo dopo passo
- Definire una funzione di decorazione esterna che accetta la funzione di destinazione come argomento.
- Importa e applica @functools.wraps(func) sulla funzione wrapper nidificata per proteggere i metadati originali.
- Implementa wrapper(*args, **kwargs) per acquisire variabili di input, inserire logica e richiamare la funzione di destinazione.
- Restituisce l'oggetto funzione wrapper dal blocco di intestazione del decoratore.
- Applica il decoratore utilizzando @decorator_name direttamente sopra la firma della funzione di destinazione.
Domande frequenti
Perché @functools.wraps è necessario all'interno dei decoratori?
Senza wrap, la funzione decorata perde la sua identità originale (i suoi attributi __name__ e __doc__ vengono sostituiti da quelli della funzione wrapper nidificata), il che rende difficile il debug e l'introspezione del codice.
Posso applicare più decoratori a una singola funzione?
Sì! Puoi concatenare i decoratori posizionando in pila più righe @. Python li applica dal basso verso l'alto (il più vicino alla definizione della funzione viene eseguito per primo).
Argomenti correlati
Padroneggia *args e **kwargs in Python. Scopri come scrivere funzioni flessibili con argomenti posizionali e parole chiave dinamici, decomprimere raccolte e creare funzioni wrapper.
Come utilizzare le funzioni Lambda in PythonScopri come utilizzare le funzioni lambda in Python. Padroneggia funzioni anonime, callback in linea e dati di elenchi di ordinamento con chiavi lambda.
Risorse Python consigliate
Espandi le tue conoscenze con tutorial interattivi, foglietti illustrativi e confronti di codici correlati.
Spiegazione delle variabili Python e dei tipi di dati
Comprendere le variabili Python e i tipi di dati principali (stringhe, numeri interi, float, booleani). Una guida completa per principianti all'assegnazione della memoria in Python.
Foglio informativo sui metodi del dizionario Python
Impara i metodi del dizionario Python. Guida di riferimento completa per inserimenti, recuperi, aggiornamenti e controlli di coppie chiave-valore.
Python vs JavaScript: quale linguaggio di programmazione è il migliore?
Un confronto completo tra Python e JavaScript. Esplora le differenze di sintassi, le prestazioni, i casi d'uso (backend e frontend) ed esempi di codifica.