ProgrammazioneSviluppatore Python

Spiega come funzionano gli argomenti *args e **kwargs nelle funzioni Python. A cosa servono, quali sono i pericoli di un uso scorretto e come combinarli correttamente con argomenti normali e nominati?

Supera i colloqui con l'assistente IA Hintsage

Risposta

*args raccoglie un numero arbitrario di argomenti posizionali in una tupla.

**kwargs raccoglie un numero arbitrario di argomenti nominati (chiave=valore) in un dizionario.

Questo permette di scrivere funzioni con un'interfaccia flessibile:

def my_func(a, b, *args, **kwargs): print(a, b) print(args) print(kwargs) my_func(1, 2, 3, 4, x=10, y=20) # 1 2 # (3, 4) # {'x': 10, 'y': 20}

Aspetti da considerare:

  • Gli argomenti normali vengono prima, seguiti da *args, poi gli argomenti nominati con valori di default e infine **kwargs — in questo ordine rigoroso durante la dichiarazione della funzione.
  • È possibile "esplodere" sequenze tramite * e dizionari tramite ** quando si chiama la funzione.
  • Non è possibile ridefinire gli stessi parametri — si otterrà un errore TypeError.

Domanda ingannevole

È possibile cambiare l'ordine di *args e argomenti nominati con un valore di default, ad esempio:

def foo(a, *args, x=10, **kwargs): pass

oppure è sempre necessario mettere i valori di default dopo *args?

Risposta:

In Python 3 sì! Ecco come (non funzionava in Python 2):

def foo(a, *args, x=10): pass

I parametri dopo *args ("keyword-only arguments") possono avere valori di default o essere obbligatori — possono essere specificati solo per nome.

Esempi di errori reali a causa della mancata comprensione dei dettagli del tema


Storia

Passaggio di argomenti errati tramite *args/**kwargs

Nei servizi REST API, l'automazione del marshalling dei dati era costruita tramite **kwargs. Un parametro superfluo non è stato notato — la funzione accettava un valore inaspettato in kwargs, causando la perdita della logica di controllo e bug difficili da individuare.


Storia

Duplicazione di argomenti nominati

Quando la funzione è stata chiamata, lo sviluppatore ha accidentalmente specificato un parametro sia esplicitamente che tramite **kwargs, ad esempio: my_func(a=1, **{"a": 2}). Di conseguenza, si è verificato un TypeError e il servizio è caduto.


Storia

Dimenticati argomenti posizionali o solo nominati

Scrivendo un decoratore, un passaggio errato dei parametri (non seguendo l'ordine e la struttura) ha portato a far sì che la funzione originale ricevesse un numero errato di argomenti, le cui convenzioni cambiavano, e in produzione hanno iniziato a sorgere errori di chiamata TypeError.