Menu

*args e **kwargs in Python: argomenti posizionali e keyword flessibili

Cosa significano *args e **kwargs, quando usarli e come inoltrare gli argomenti da una funzione all'altra in modo pulito.

Questa pagina include editor eseguibili: modifica, esegui e vedi subito l'output.

Quando non sai quanti argomenti arriveranno

La maggior parte delle funzioni accetta un numero fisso di parametri. A volte però serve qualcosa di più flessibile: un logger che accetta un numero qualsiasi di messaggi, una funzione wrapper che inoltra a un'altra funzione tutto quello che ha ricevuto, una funzione di plotting che accetta una configurazione senza sapere esattamente quali opzioni userà chi la chiama.

Python risolve il problema con due marcatori speciali nella lista dei parametri: *args e **kwargs.

*args raccoglie gli argomenti posizionali

Un solo asterisco significa "metti tutti gli argomenti posizionali in più in una tupla":

Dentro la funzione, args è una normale tupla. Puoi scorrerla con un ciclo, accedere ai suoi elementi per indice, passarla a len() o farne uno slice.

*args compare di solito insieme a parametri con nome:

first prende il primo argomento; *rest mette tutto il resto in una tupla.

**kwargs raccoglie gli argomenti keyword

Due asterischi fanno la stessa cosa per gli argomenti keyword, raccogliendoli in un dict:

Dentro describe, kwargs è un normale dict. Le chiavi sono i nomi degli argomenti keyword, come stringhe.

Usarli insieme

Puoi usarli entrambi nella stessa funzione. Per convenzione *args viene prima di **kwargs:

L'ordine completo dei parametri, dal primo all'ultimo, è:

  1. Parametri posizionali normali (obbligatori o con valori predefiniti).
  2. *args.
  3. Parametri solo keyword (tutto ciò che viene dopo *args va passato per nome).
  4. **kwargs.

title prende il primo argomento posizionale. Gli altri posizionali finiscono in tags. draft va passato per nome (viene dopo *tags). Tutti gli altri argomenti keyword finiscono in metadata.

Spacchettare con * e ** nella chiamata

Gli asterischi funzionano anche al contrario: distribuiscono una sequenza o un dict negli argomenti di una chiamata:

È comodissimo per inoltrare argomenti:

wrapped non ha bisogno di sapere quali argomenti si aspetta log. Raccoglie tutto e lo inoltra. Questo schema compare di continuo nei decoratori (un argomento più avanzato) e nelle funzioni wrapper.

Quando *args e **kwargs sono la scelta sbagliata

È facile farsi prendere la mano e usarli ovunque. Due avvertenze:

Nascondono cosa si aspetta una funzione

Se ogni funzione del tuo codice è def f(*args, **kwargs), chi la chiama non ha idea di quali argomenti siano validi. Usa parametri con nome ogni volta che puoi, e lascia a *args/**kwargs solo gli input davvero variabili o il puro inoltro.

I messaggi di errore diventano vaghi

Un nome keyword scritto male diventa un None silenzioso o un KeyError in fondo alla funzione, invece di un immediato "unexpected keyword argument" nel punto della chiamata. I parametri con nome ti danno un feedback molto migliore.

Come regola: preferisci i parametri con nome, e ricorri a *args/**kwargs solo quando la funzione è davvero flessibile o sta inoltrando argomenti a un altro callable.

Un piccolo esempio pratico

Un helper in stile plotting che avvolge una funzione di terze parti con qualche valore predefinito:

*values permette a chi chiama di passare un numero qualsiasi di elementi; **style assorbe la configurazione in più senza che ogni opzione debba essere un parametro con nome. È flessibile senza essere opaco, perché la logica interna ti dice esattamente quali chiavi legge da style.

  • *args raccoglie gli argomenti posizionali in più in una tupla.
  • **kwargs raccoglie gli argomenti keyword in più in un dict.
  • Nella chiamata, *seq e **dict spacchettano nella direzione opposta.
  • I parametri devono comparire in questo ordine: normali → *args → solo keyword → **kwargs.
  • Non esagerare: quando puoi usarli, i parametri con nome sono più chiari.

Prossimo argomento: lambda, un modo per scrivere al volo piccole funzioni usa e getta.

Domande frequenti

Cos'è *args in Python?

*args raccoglie tutti gli argomenti posizionali in più in una tupla. def f(*args): ti permette di chiamare f(1, 2, 3) e ricevere args come (1, 2, 3). Il nome args è una convenzione: potresti chiamarlo in qualsiasi modo, ma *args è quello che usano tutti.

Cos'è **kwargs in Python?

**kwargs raccoglie tutti gli argomenti keyword in più in un dict. def f(**kwargs): ti permette di chiamare f(name='Ada', age=30) e ricevere kwargs come {'name': 'Ada', 'age': 30}. Insieme, *args e **kwargs permettono a una funzione di accettare qualsiasi combinazione di argomenti.

Devo per forza chiamarli args e kwargs?

No, contano gli asterischi, non i nomi. *values e **options funzionano allo stesso modo. Però args e kwargs sono una convenzione quasi universale nel codice Python: usali, a meno che tu non abbia un motivo preciso per scegliere qualcosa di più descrittivo.

Illustrazione dei linguaggi di programmazione di Coddy

Impara a programmare con Coddy

INIZIA