Come usare argomenti di lunghezza variabile (*args, **kwargs) in Python

Attività commerciale

I seguenti argomenti di funzione sono probabilmente i più comuni che vi lasciano perplessi quando guardate il codice Python e dite: “Cos'è questo?

  • *args
  • **kwargs

Qualsiasi numero di argomenti (argomenti di lunghezza variabile) può essere specificato aggiungendo un asterisco all'argomento nella definizione della funzione come segue

  • *
  • **

I nomi *args,**kwargs sono spesso usati come convenzione. Tuttavia, altri nomi sono accettabili purché * e ** siano all'inizio. Il seguente codice di esempio usa i nomi *args,**kwargs.

I seguenti dettagli sono descritti di seguito.

  • *args:Accetta più argomenti come una tupla
  • **kwargs:Accetta argomenti multipli di parole chiave come un dizionario

*args: Accetta più argomenti come una tupla

Un numero arbitrario di argomenti può essere specificato definendo gli argomenti con *, come in *args.

def my_sum(*args):
    return sum(args)

print(my_sum(1, 2, 3, 4))
# 10

print(my_sum(1, 2, 3, 4, 5, 6, 7, 8))
# 36

Gli argomenti multipli sono ricevuti come una tupla nella funzione. Nell'esempio, alla funzione sum() viene passata una tupla per calcolare la somma.

def my_sum2(*args):
    print('args: ', args)
    print('type: ', type(args))
    print('sum : ', sum(args))

my_sum2(1, 2, 3, 4)
# args:  (1, 2, 3, 4)
# type:  <class 'tuple'>
# sum :  10

Può anche essere combinato con un argomento di posizione.

Il valore specificato dopo (a destra di) l'argomento posizionale viene passato ad args come una tupla. Se c'è solo un argomento posizionale, è una tupla vuota.

def func_args(arg1, arg2, *args):
    print('arg1: ', arg1)
    print('arg2: ', arg2)
    print('args: ', args)

func_args(0, 1, 2, 3, 4)
# arg1:  0
# arg2:  1
# args:  (2, 3, 4)

func_args(0, 1)
# arg1:  0
# arg2:  1
# args:  ()

Gli argomenti marcati con * possono essere definiti per primi. In questo caso, tuttavia, gli argomenti definiti dopo *args devono essere specificati in forma di parola chiave. Per inciso, il formato parola chiave è la forma “nome argomento = valore”.

L'ultimo valore non viene automaticamente passato all'argomento posizionale. Pertanto, se non è specificato come argomento di parola chiave, risulterà un errore TypeError.

def func_args2(arg1, *args, arg2):
    print('arg1: ', arg1)
    print('arg2: ', arg2)
    print('args: ', args)

# func_args2(0, 1, 2, 3, 4)
# TypeError: func_args2() missing 1 required keyword-only argument: 'arg2'

func_args2(0, 1, 2, 3, arg2=4)
# arg1:  0
# arg2:  4
# args:  (1, 2, 3)

Se vengono specificati solo * argomenti, gli argomenti successivi devono sempre essere specificati come argomenti di parole chiave.(keyword-only argument)

def func_args_kw_only(arg1, *, arg2):
    print('arg1: ', arg1)
    print('arg2: ', arg2)

# func_args_kw_only(100, 200)
# TypeError: func_args_kw_only() takes 1 positional argument but 2 were given

func_args_kw_only(100, arg2=200)
# arg1:  100
# arg2:  200

**kwargs: Accetta argomenti multipli di parole chiave come un dizionario

Un numero arbitrario di argomenti di parole chiave può essere specificato definendo gli argomenti con ,** come in **kwargs.

Nella funzione, il nome dell'argomento viene ricevuto come un dizionario la cui chiave è la chiave e il cui valore è il valore.

def func_kwargs(**kwargs):
    print('kwargs: ', kwargs)
    print('type: ', type(kwargs))

func_kwargs(key1=1, key2=2, key3=3)
# kwargs:  {'key1': 1, 'key2': 2, 'key3': 3}
# type:  <class 'dict'>

Può anche essere usato insieme a un argomento di posizione.

def func_kwargs_positional(arg1, arg2, **kwargs):
    print('arg1: ', arg1)
    print('arg2: ', arg2)
    print('kwargs: ', kwargs)

func_kwargs_positional(0, 1, key1=1)
# arg1:  0
# arg2:  1
# kwargs:  {'key1': 1}

Specificando l'oggetto dizionario con ** come argomento quando si chiama la funzione, è possibile espanderlo e passarlo come rispettivo argomento.

d = {'key1': 1, 'key2': 2, 'arg1': 100, 'arg2': 200}

func_kwargs_positional(**d)
# arg1:  100
# arg2:  200
# kwargs:  {'key1': 1, 'key2': 2}

Gli argomenti marcati con ** possono essere definiti solo alla fine dell'argomento. Definire un altro argomento dopo l'argomento marcato con ** risulterà in un errore di SyntaxError.

# def func_kwargs_error(**kwargs, arg):
#     print(kwargs)

# SyntaxError: invalid syntax