Quante volte ti sei trovato a scrivere una funzione di tre o quattro righe solo per doverla usare una volta sola e poi dimenticarla da qualche parte nel file?
Le funzioni lambda in Python servono esattamente a questo: snellire il codice, evitare di inquinare lo script con definizioni inutili e risolvere problemi “al volo”.
In questo articolo vedremo tre esercizi pratici, dal più semplice al più insidioso, per capire quando e come usare queste funzioni anonime.
Esercizio 1: Il Quadrato Semplice (e la regola d’oro)
La Sfida: Stai sviluppando uno script per un laboratorio di fisica e devi calcolare rapidamente il quadrato di una serie di misure. Scrivi una funzione lambda che restituisca il quadrato di un numero e usala con map() per elevare al quadrato i valori della lista [3, 5, 7, 9].
La Soluzione:
# Lista di input
numeri = [3, 5, 7, 9]
# Applico map passando direttamente la lambda (best practice)
risultati = map(lambda x: x * x, numeri)
# Converto l'iteratore in lista per stampare i valori
lista_quadrati = list(risultati)
print(lista_quadrati)
Output: [9, 25, 49, 81]
Dietro le quinte:
Una lambda è una funzione anonima definita in una sola riga: lambda argomenti: espressione.
Non serve scrivere return perché il risultato viene restituito in automatico. Usata insieme a map(), permette di applicare una logica a ogni elemento di un iterabile risparmiando molta memoria.
💡 In sintesi: La lambda è un’espressione “usa-e-getta” perfetta per trasformare rapidamente una lista di dati tramite
map().
Domanda di riflessione: Qual è la vera differenza tra una funzione definita con def e una lambda?
Risposta: La differenza pratica è che def crea uno statement complesso (con cicli, più righe, gestione degli errori), ha un nome ufficiale e compare nei log di errore. La lambda è solo un’espressione.
Attenzione: assegnare una lambda a una variabile (es. quad = lambda x: x*x) è considerato un “peccato” dalla PEP 8 di Python. Se devi darle un nome, usa def! Le lambda vanno usate “inline”.
⚠️ Approfondimento: Perché non dovresti mai dare un nome a una Lambda
Mentre ti eserciti, potresti essere tentato di scrivere qualcosa come quadrato = lambda x: x * x.
Funziona? Sì. È un buon codice Python? No.
La PEP 8, il manuale di stile ufficiale di Python, contiene una regola specifica (la E731) che sconsiglia caldamente di assegnare una lambda a una variabile. Il motivo è semplice: se una funzione ha un nome, non dovrebbe essere “anonima”.
Ecco i tre motivi principali per cui assegnare nomi alle lambda è considerato un “peccato” di programmazione:
1. L’incubo del Debugging
Il limite più grande è tecnico. Quando definisci una funzione con def, Python le assegna un nome ufficiale (attributo __name__). Quando crei una lambda, per Python il suo nome è sempre e solo <lambda>.
Se il tuo codice si rompe, il traceback (il messaggio di errore) ti dirà:
-
Con
def:Errore nella funzione calcola_distanza alla riga 10. (Chiaro e veloce). -
Con
lambdaassegnata:Errore nella funzione <lambda> alla riga 10.
Se hai dieci lambda nel tuo script, buona fortuna a capire quale sia quella che ha generato il problema!
2. Una contraddizione logica
Le lambda nascono per essere funzioni anonime usa-e-getta. Se senti il bisogno di dare un nome a una logica (come quadrato o filtro_eta), significa che quella logica è abbastanza importante da meritare una struttura propria. Usare una lambda e poi darle un nome è come comprare un piatto usa-e-getta e poi cercare di lavarlo e conservarlo in credenza: un controsenso.
3. Niente “Docstring” o Aiuti
Le funzioni definite con def sono molto più generose. Ti permettono di:
-
Aggiungere Docstring (commenti multiriga che spiegano cosa fa la funzione).
-
Usare i Type Hints (per dire a Python che tipi di dati ti aspetti, es.
x: int). -
Scrivere logiche su più righe per non affaticare la vista.
Nelle lambda tutto questo è impossibile: sei confinato in una singola, stretta riga di codice.
Quando usare allora le Lambda?
La regola d’oro è: usale “Inline”. Le lambda brillano quando vengono passate direttamente come argomento a un’altra funzione, senza mai essere salvate in una variabile.
✅ Esempio Corretto (Inline):
# La lambda nasce e muore dentro sorted(), non ha nome. punti_ordinati = sorted(punti, key=lambda p: p[0]**2 + p[1]**2)
# PEP 8 Error: se serve un nome, usa 'def' formula_distanza = lambda p: p[0]**2 + p[1]**2 punti_ordinati = sorted(punti, key=formula_distanza)
def. Se devi passarla al volo e poi dimenticartene, usa lambda.Esercizio 2: Distanza tra due punti nel piano
La Sfida:
Hai una lista di coordinate nel piano cartesiano e devi ordinarle in base alla loro distanza dall’origine (0,0). Scrivi una lambda da usare come “chiave” di ordinamento nella funzione sorted(). Infine, estrai il punto più lontano. Lista: [(3,4), (1,1), (5,12), (0,0), (2,2)]
La Soluzione:
punti = [(3,4), (1,1), (5,12), (0,0), (2,2)]
# Usiamo la lambda direttamente nel parametro key di sorted.
# Distanza al quadrato = x^2 + y^2.
punti_ordinati = sorted(punti, key=lambda p: p[0]**2 + p[1]**2)
print("Punti ordinati:", punti_ordinati)
# Output: [(0, 0), (1, 1), (2, 2), (3, 4), (5, 12)]
punto_max = punti_ordinati[-1]
# Calcoliamo la distanza reale solo per la stampa finale
distanza_reale = (punto_max[0]**2 + punto_max[1]**2)**0.5
print(f"Punto più lontano: {punto_max} con distanza {distanza_reale:.2f}")
Punti ordinati: [(0, 0), (1, 1), (2, 2), (3, 4), (5, 12)]
Punto più lontano: (5, 12) con distanza 13.00
Dietro le quinte:
Il parametro key di sorted() accetta una funzione. Invece di scrivere una def apposita, gli passiamo una lambda che “insegna” a Python come valutare ogni tupla. Il trucco matematico qui è usare la distanza al quadrato (x2 + y2) senza estrarre la radice. Poiché la radice è monotona crescente, l’ordinamento rimane identico, ma il calcolo è molto più veloce.
💡 In sintesi: Usare una lambda come
keyinsorted()permette di personalizzare l’ordinamento di strutture complesse senza creare funzioni esterne.
Domanda di riflessione: Cosa succede se la funzione key restituisce valori non confrontabili tra loro?
Risposta: Python non saprebbe come ordinarli e lancerebbe un TypeError. Affinché sorted() funzioni, la chiave deve generare un ordine totale (numeri con numeri, o stringhe con stringhe). Nota: le liste in Python sono confrontabili tra loro in modo lessicografico, ma si otterrebbe un errore se all’interno delle liste ci fossero tipi misti (es. un intero e una stringa).
Esercizio 3: Categorizzazione con Condizione Ternaria
La Sfida: Un’azienda classifica l’età degli utenti:
-
“giovane” se età < 18
-
“adulto” se 18 ≤ età < 65
-
“anziano” se età ≥ 65 Usa una lambda all’interno di
map()per convertire la listaeta = [12, 25, 70, 17, 65]nelle relative etichette. Poi, usafilter()per isolare solo le età dei “giovani”.
La Soluzione:
# Mappatura con operatore ternario annidato
categorie = list(map(lambda e: "giovane" if e < 18 else ("adulto" if e < 65 else "anziano"), eta))
print("Categorie:", categorie)
# Output: ['giovane', 'adulto', 'anziano', 'giovane', 'anziano']
# Filtro
giovani = list(filter(lambda e: e < 18, eta))
print("Giovani (età):", giovani)
Categorie: ['giovane', 'adulto', 'anziano', 'giovane', 'anziano']
Giovani (età): [12, 17]
Dietro le quinte:
Dato che una lambda non supporta il classico blocco if-elif-else multilinea, dobbiamo affidarci all’operatore ternario di Python (valore_se_vero if condizione else valore_se_falso). Se le condizioni sono più di due, possiamo annidarli. filter() invece fa un lavoro diverso: tiene solo gli elementi per i quali la lambda restituisce True.
💡 In sintesi: La lambda può gestire logiche di scelta grazie all’operatore
if-elsein linea, rendendo immediata la categorizzazione o il filtraggio dei dati.
Domanda di riflessione: Si può scrivere una lambda per verificare pari o dispari? E perché non posso usare un costrutto if...elif classico dentro una lambda?
Risposta: Sì: lambda n: "pari" if n % 2 == 0 else "dispari". Non puoi usare un normale if...elif...else perché la sintassi richiede che la lambda contenga esclusivamente un’espressione che restituisce un valore, non uno statement di controllo del flusso.
🛠️ Quando usare una Lambda?
Per evitare di abusare delle funzioni anonime, applica la regola delle 3 Condizioni.
Puoi usare una lambda solo se tutte e tre sono soddisfatte:
-
Unicità: La logica serve solo in quel punto preciso del codice e non verrà mai riutilizzata altrove.
-
Sola Espressione: La logica può essere scritta in una singola riga di codice senza dover usare punti e virgola o acrobazie sintattiche.
-
Chiarezza Immediata: Il nome degli argomenti e l’operazione sono così intuitivi che non servono commenti per spiegarli.
⏱️ Il “Test dei 5 Secondi”
Questo è il gold standard della leggibilità in Python. Quando scrivi una lambda (magari una complessa con operatori ternari come nell’Esercizio 3), distogli lo sguardo per un momento e poi riguardala:
Se non riesci a capire esattamente cosa fa la lambda in meno di 5 secondi, non deve essere una lambda.
Se ti ritrovi a strizzare gli occhi per seguire le parentesi o i blocchi if-else annidati, fermati: cancella tutto e scrivi una funzione tradizionale con def.
Il te stesso del futuro (quello che dovrà fare manutenzione al codice tra sei mesi) ti ringrazierà infinitamente.
Riassunto finale dei concetti chiave
Per chiudere l’articolo in bellezza, ecco i punti fermi da portare a casa:
| Situazione | Strumento consigliato | Perché? |
Trasformazione rapida in map/filter |
Lambda | Codice compatto e “inline”. |
| Logica riutilizzabile in più file | Def | Facile da importare e testare. |
| Operazioni con cicli o più istruzioni | Def | La lambda non supporta i blocchi di codice. |
| Debugging di sistemi critici | Def | I nomi delle funzioni appaiono nei log di errore. |
L.A.M.B.D.A.™🐍
- Logica usa‑e‑getta
- Atomicità (una sola espressione)
- Mantenibilità immediata
- Brevità senza sacrificare chiarezza
- Debug limitato → evitare nomi
- Applicazione inline
Ora che sai quando NON usare una lambda, prova a trasformare l’esercizio 1 usando una List Comprehension. Quale delle due versioni ti sembra più chiara dopo aver applicato il Test dei 5 Secondi?
Applicazioni Pratiche
-
Esercizio 1 (Data Engineering): L’uso di
map()con le lambda è la base concettuale di framework di calcolo distribuito come Spark o dei DataFrame in Pandas (tramite il metodo.apply()). Questo esercizio è interessante perché abitua la mente a pensare in modo funzionale: non modifichiamo i dati iterando con unfor, ma applichiamo una trasformazione globale all’intero set di dati in un colpo solo. -
Esercizio 2 (Ottimizzazione Algoritmica): Questo è un classico problema da Game Development o da calcolo spaziale (Geospatial Analysis). La vera perla dell’esercizio è l’astuzia matematica: evitare il calcolo della radice quadrata (costoso a livello di CPU) per effettuare un semplice ordinamento. In scenari con milioni di punti (es. algoritmi di clustering come K-Means), ottimizzare la lambda eliminando la radice fa risparmiare preziosi secondi di computazione.
-
Esercizio 3 (Data Cleaning): Questo esercizio simula perfettamente un’operazione di binning (raggruppamento in classi), un’attività quotidiana per i Data Analyst. Il fascino di questo esercizio risiede nel “forzare” i limiti della lambda tramite il ternario annidato. Tuttavia, insegna anche una lezione di design del codice: se inizi ad annidare tre o quattro ternari in una lambda, perdi del tutto la leggibilità e diventa preferibile usare una classica
def.
Articoli di approfondimento
👉 Liste Python: guida completa ai metodi essenziali
👉 Guida a map() in Python: Scrivere Codice Elegante e Veloce con Esempi Pratici
👉 Imparare Python: esercizi pratici sulle liste con soluzioni
👉 List comprehension: esercizi pratici su matrici e dati
👉Come usare le comprehension: scrivere codice più efficiente





