Funzioni Lambda di Python: Sintassi, usi reali e quando non usarli
Una lambda è una piccola funzione che puoi scrivere su una riga, proprio dove ti serve. Impara la sintassi, i luoghi in cui i lambda aiutano veramente, la trappola che cattura gli sviluppatori esperti e quando una funzione normale è semplicemente migliore.
- Una lambda è una funzione anonima limitata a una singola espressione.
- Il suo utilizzo migliore è come argomento breve, in particolare
keypersorted,minemax. - La comprensione di una lista è solitamente più chiara di
mapofiltercon una lambda. - Se assegni una lambda a un nome, scrivi invece un
def.
È necessario ordinare i prodotti in base al prezzo. Scrivere una funzione con nome separato solo per dire “usa il prezzo” sembra una sorta di cerimonia. Le funzioni lambda di Python ti consentono di definire quel piccolo pezzo di logica in linea, esattamente dove lo usi.
I Lambda sono utili, ma sono anche facili da abusare. Questa guida mostra dove aiutano veramente e dove rendono il codice più difficile da leggere. Abbiamo eseguito ogni esempio su Python 3.13 e l’output mostrato proviene da quell’esecuzione.
Cos’è una lambda?
Una lambda è una funzione senza nome, scritta con la parola chiave lambda:
lambda arguments: expression
Accetta un numero qualsiasi di argomenti e restituisce automaticamente il valore di una singola espressione. Non esiste una parola chiave return e nessun insieme di istruzioni.
square = lambda x: x * x
print(square(4)) # 16
print((lambda a, b=10: a + b)(5)) # 15
La seconda riga definisce una lambda con un argomento predefinito e la chiama immediatamente. Raramente lo scriveresti in codice reale, ma mostra che un lambda è un oggetto funzione ordinario.
lambda contro def
Questi due producono funzioni che si comportano allo stesso modo:
square = lambda x: x * x
def square_def(x):
return x * x
print(square(4), square_def(4)) # 16 16
print(square.__name__, square_def.__name__) # <lambda> square_def
Guarda i nomi. Ogni lambda è chiamato semplicemente <lambda>, quindi i messaggi di errore e i log non possono dirti quale ha avuto esito negativo. Questo è il motivo principale per cui le guide di stile come PEP 8 consigliano un def ogni volta che si desidera dare un nome a una funzione.
| Caratteristica | lambda |
def |
|---|---|---|
| Nome | Anonimo | Nominato |
| Corpo | Una sola espressione | Qualsiasi numero di dichiarazioni |
| Ritorno | Implicito | esplicito return |
| Docstring e suggerimenti sul tipo | Non supportato | Supportato |
| Tracce leggibili | Spettacoli <lambda> |
Mostra il nome |
| Meglio per | Brevi argomentazioni usa e getta | Tutto il resto |
Ordinamento con chiave: il miglior utilizzo
Funzioni come sorted, min e max accettano una funzione key che decide cosa confrontare. È qui che brillano le lambda:
products = [("pen", 10), ("bag", 900), ("book", 250)]
sorted(products, key=lambda p: p[1])
# [('pen', 10), ('book', 250), ('bag', 900)]
max(products, key=lambda p: p[1])
# ('bag', 900)
Per ordinare in base a più elementi, restituire una tupla. Qui le persone sono ordinate per età, prima il più anziano e poi per nome:
people = [{"name": "Asha", "age": 31}, {"name": "Ben", "age": 25},
{"name": "Dev", "age": 31}]
[p["name"] for p in sorted(people, key=lambda p: (-p["age"], p["name"]))]
# ['Asha', 'Dev', 'Ben']
Il segno meno inverte l’ordine solo per il numero. A volte non è affatto necessario un lambda, perché una funzione esistente fa già il lavoro. Confronta l’ordinamento predefinito con uno senza distinzione tra maiuscole e minuscole:
names = ["Asha", "ben", "Chitra", "dev"]
sorted(names) # ['Asha', 'Chitra', 'ben', 'dev']
sorted(names, key=str.lower) # ['Asha', 'ben', 'Chitra', 'dev']
Per impostazione predefinita, tutte le parole in maiuscolo vengono messe per prime. Passare str.lower risolve il problema senza lambda. Il modulo operator offre aiutanti simili, come itemgetter(1) per lambda p: p[1].
mappare e filtrare
map applica una funzione a ogni elemento e filter mantiene gli elementi per i quali restituisce true. Entrambi funzionano con lambda, ma confrontali ciascuno con una comprensione di elenco:
nums = [1, 2, 3, 4, 5, 6]
list(map(lambda n: n * 10, nums)) # [10, 20, 30, 40, 50, 60]
[n * 10 for n in nums] # [10, 20, 30, 40, 50, 60]
list(filter(lambda n: n % 2 == 0, nums)) # [2, 4, 6]
[n for n in nums if n % 2 == 0] # [2, 4, 6]
I risultati sono identici e la maggior parte degli sviluppatori Python trova le comprensioni più facili da leggere. Nota anche che map e filter restituiscono iteratori pigri, quindi è necessario list() per vedere i valori. La nostra guida alla comprensione dell’elenco Python tratta questo stile in modo approfondito. map funziona ancora bene con una funzione con nome esistente, come in map(str.strip, lines).
ridurre
functools.reduce combina gli elementi in un unico valore, portando un risultato corrente:
from functools import reduce
reduce(lambda acc, n: acc + n, nums, 0) # 21
sum(nums) # 21
Per i lavori comuni, come i totali, utilizzare un built-in come sum, max o any. Mantieni reduce per i casi più rari e considera un ciclo semplice se la lambda inizia a sembrare complicata.
Condizioni in una lambda
Non puoi utilizzare un’istruzione if in una lambda, ma puoi utilizzare un’espressione condizionale:
label = lambda total: "large" if total >= 1000 else "small"
label(1200), label(300)
# ('large', 'small')
Una condizione va bene. Una volta che inizi a nidificarli, i lettori devono lavorare sodo, il che è un chiaro segno per passare a def con istruzioni if ordinarie.
Lambda che restituiscono funzioni
Una funzione può creare e restituire un lambda che ricorda un valore dall’ambiente circostante:
def multiplier(n):
return lambda x: x * n
double = multiplier(2)
double(7) # 14
Funziona grazie alle chiusure, che il nostro articolo sulle chiusure JavaScript spiega in una lingua diversa. Python functools.partial offre un altro modo per precompilare gli argomenti.
La trappola del legame tardivo
Questo alla fine cattura quasi tutti. Abbiamo creato tre lambda in un ciclo, aspettandoci che ciascuno restituisca il proprio numero:
funcs = [lambda: i for i in range(3)]
[f() for f in funcs]
# [2, 2, 2]
Tutti e tre restituiscono 2. Una lambda non cattura il valore di i quando viene creata. Cerca la variabile quando viene chiamata, e a quel punto il ciclo è terminato, lasciando i su 2. La soluzione usuale è acquisire il valore come argomento predefinito, poiché i valori predefiniti vengono valutati al momento della definizione:
funcs = [lambda i=i: i for i in range(3)]
[f() for f in funcs]
# [0, 1, 2]
Questo non è esclusivo dei lambda, poiché un def all’interno di un ciclo si comporta allo stesso modo. Appare più spesso con i lambda, perché sono comunemente creati in loop, ad esempio quando si allegano callback di pulsanti.
Suggerimento: Se hai bisogno di una funzione per articolo, considera se hai bisogno di molte funzioni. Spesso una singola funzione che prende l’elemento come argomento è più chiara ed evita completamente la trappola.
Tabelle di ricerca di piccole funzioni
I lambda si adattano perfettamente a un dizionario che associa i nomi a piccole operazioni:
ops = {
"add": lambda a, b: a + b,
"sub": lambda a, b: a - b,
}
ops["sub"](10, 3) # 7
Questo può sostituire una lunga catena di if e elif. La guida al dizionario Python copre più modelli di dizionario e il modulo operator fornisce già operator.add e operator.sub.
Limiti delle lambda
- Solo un’espressione. Nessuna assegnazione con
=, nessun loop e nessun bloccotry. - Nessuna dichiarazione. Scrivere
lambda x: return xfallisce con unSyntaxError, come confermato dal nostro test. - Nessuna stringa di documento o suggerimento sul tipo. Strumenti e lettori ricevono meno aiuto.
- Debug più difficile. Gli errori puntano a
<lambda>anziché a un nome utile.
Ovviamente i Lambda possono ancora sollevare eccezioni. La loro gestione funziona allo stesso modo di qualsiasi altra funzione, come spiegato in Gestione delle eccezioni Python.
Quando non utilizzare una lambda
| Situazione | Scelta migliore |
|---|---|
| Assegnandolo a un nome | def |
| La logica ha bisogno di più di una riga | def |
| Trasformare o filtrare un elenco | Una comprensione dell’elenco |
| Sommare o trovare un massimo | sum, max, min |
| Ottenere un oggetto o un attributo | operator.itemgetter o attrgetter |
| La stessa lambda appare in più punti | Una funzione con nome che puoi testare |
Quest’ultimo punto è importante. Vale la pena testare la logica che vale la pena riutilizzare e una funzione con nome è molto più semplice da testare, come mostra il nostro tutorial pytest.
Considerazioni finali
Un buon lambda è abbastanza corto da poter essere letto a colpo d’occhio e usato una volta, di solito come argomento. Le chiavi di ordinamento sono l’esempio classico. Per controllare il tuo codice, cerca = lambda e trasformalo in funzioni con nome. Quindi guarda qualsiasi map o filter con una lambda e vedi se una comprensione si legge meglio.
Domande frequenti
Cos’è una funzione lambda in Python?
È una piccola funzione anonima creata con la parola chiave lambda. Accetta argomenti e restituisce il valore di una singola espressione, senza un nome o un’istruzione return.
Un lambda Python può avere più righe?
No. Una lambda è limitata a un’espressione. Puoi dividerlo su righe tra parentesi, ma non può comunque contenere istruzioni, quindi usa def per una logica più complessa.
Posso usare if else in una lambda?
Puoi utilizzare un’espressione condizionale, ad esempio lambda x: “grande” se x > 10 altrimenti “piccolo”. Non è consentita un’istruzione if con un blocco.
Le lambda sono più veloci delle normali funzioni?
Non in modo significativo. Entrambi creano lo stesso tipo di oggetto funzione. Scegli tra loro per la leggibilità, non per le prestazioni.
Dovrei usare la mappa con lambda o una comprensione dell’elenco?
La maggior parte degli sviluppatori Python preferisce una comprensione dell’elenco per la leggibilità. map è ragionevole quando hai già una funzione con nome, come map(str.strip, lines).
Continua a imparare
Hai bisogno di aiuto con test, WordPress o SEO?
Aiutiamo i team a fornire software migliore e a far crescere i loro siti. Raccontaci a cosa stai lavorando e ti suggeriremo chiaramente il prossimo passo.
Altre guide su test, intelligenza artificiale e sviluppo moderno
Ti è piaciuto questo articolo? Scegli un argomento e passa direttamente ai nostri tutorial più recenti.
Spiegazione delle allucinazioni dell'intelligenza artificiale: perché i modelli linguistici inventano le cose e come ridurle
Spiegazione delle allucinazioni dell'intelligenza artificiale: cosa sono, perché i modelli linguistici le producono, tipi comuni, come ridurle con b…
Leggi l'articolo →DevOpsSpiegazione delle variabili d'ambiente: file .env, segreti e configurazione eseguiti correttamente
Variabili d'ambiente spiegate con esempi Python che abbiamo eseguito: lettura e impostazione, perché ogni valore è una stringa, file .env, ereditari…
Leggi l'articolo →Sviluppo softwareSpiegazione della limitazione della velocità API: algoritmi, intestazioni e gestione degli errori 429
La limitazione della velocità dell'API spiegata con una simulazione che abbiamo eseguito: bucket di token, finestra fissa, finestra scorrevole, risp…
Leggi l'articolo →Automazione dei testDerisione in Python: unittest.mock, patch e gli errori che fanno mentire i test
Mocking in Python con unittest.mock, testato: Mock e return_value, side_effect, patch dove viene utilizzato un nome, specifiche e autospec, date moc…
Leggi l'articolo →Test del softwareSpiegazione della copertura del codice: copertura di linea o di filiale e cosa significa realmente il 100%.
Copertura del codice spiegata con una vera esecuzione di cover.py: copertura di linea, ramo e condizione, lettura di un rapporto, perché la copertur…
Leggi l'articolo →Database e SQLDELETE vs TRUNCATE vs DROP in SQL: differenze, rollback e quando utilizzarli
DELETE vs TRUNCATE vs DROP spiegato con SQL testato: cosa rimuove, rollback, trigger, reimpostazione dell'identità, velocità e come differiscono Pos…
Leggi l'articolo →Database e SQLSpiegazione delle visualizzazioni SQL: crea, utilizza ed evita le insidie, con esempi
Viste SQL spiegate con le query che abbiamo eseguito: creazione di una vista, risultati in tempo reale, nascondere colonne, prestazioni, viste aggio…
Leggi l'articolo →Sviluppo softwareInterfaccia TypeScript e tipo: differenze reali, testate con il compilatore
Interfaccia TypeScript vs tipo, verificata con il vero compilatore: cosa possono fare entrambi, cosa può fare solo uno, fusione delle dichiarazioni,…
Leggi l'articolo →Sviluppo softwareSpiegazione di Python *args e **kwargs: funzioni flessibili con esempi chiari
Python *args e **kwargs spiegati con il codice che abbiamo eseguito: compressione e decompressione, ordine dei parametri, argomenti solo per parole …
Leggi l'articolo →Sviluppo softwareFunzioni Lambda Python: sintassi, usi reali e quando non usarli
Funzioni lambda Python spiegate con il codice che abbiamo eseguito: sintassi, ordinamento con chiave, mappa e filtro, chiusure, trap dell'associazio…
Leggi l'articolo →Intelligenza artificialeCosa sono gli agenti AI? Come funzionano, con un semplice ciclo di agenti che puoi eseguire
Cosa sono gli agenti IA? Una semplice guida al ciclo dell'agente, agli strumenti, alla memoria e ai guardrail, con un piccolo ciclo Python che abbia…
Leggi l'articolo →DevOpsMonitoraggio vs osservabilità: la vera differenza, con log, metriche e tracce
Spiegazione del monitoraggio e dell'osservabilità: errori noti e sconosciuti, log, metriche e tracce, una procedura dettagliata sugli incidenti di p…
Leggi l'articolo →DevOpsVolumi Docker e montaggi di associazione: mantenere i dati del contenitore nel modo giusto
Volumi Docker e montaggi di collegamento spiegati: perché i dati del contenitore scompaiono, volumi denominati, montaggi di collegamento, tmpfs, ese…
Leggi l'articolo →Automazione dei testTDD vs BDD: differenze chiave, una caratteristica costruita in entrambi i modi e quando utilizzarli ciascuno
TDD vs BDD spiegato con una funzione di sconto costruita in entrambi i modi: refactoring rosso-verde con il codice che abbiamo eseguito, scenari "Da…
Leggi l'articolo →Sviluppo softwareGit merge vs rebase: differenze, esempi e quando usare ciascuno
Git merge vs rebase spiegato con output reale del log, una tabella di confronto, la regola d'oro del rebase e un flusso di lavoro sicuro per i team.
Leggi l'articolo →Sviluppo softwareList comprehension in Python: sintassi, esempi e quando evitarla
List comprehension in Python spiegata: sintassi, filtri, if-else, cicli annidati, tempi misurati e i casi in cui un normale ciclo for è meglio.
Leggi l'articolo →Database e SQLSQL JOIN spiegati con esempi (Inner, Left, Right, Full)
Capisci i JOIN SQL passo dopo passo con tabelle e query di esempio: INNER, LEFT, RIGHT, FULL, CROSS e SELF, con errori comuni e consigli sulle prest…
Leggi l'articolo →