Python Language
* args e ** kwargs
Ricerca…
Osservazioni
Ci sono alcune cose da notare:
I nomi
args
ekwargs
sono usati per convenzione, non fanno parte delle specifiche del linguaggio. Quindi, questi sono equivalenti:def func(*args, **kwargs): print(args) print(kwargs)
def func(*a, **b): print(a) print(b)
Potresti non avere più di un
args
o più di un parametrokwargs
(tuttavia non sono necessari)def func(*args1, *args2): # File "<stdin>", line 1 # def test(*args1, *args2): # ^ # SyntaxError: invalid syntax
def test(**kwargs1, **kwargs2): # File "<stdin>", line 1 # def test(**kwargs1, **kwargs2): # ^ # SyntaxError: invalid syntax
Se qualche argomento posizionale segue
*args
, sono argomenti solo per parole chiave che possono essere passati solo per nome. Una singola stella può essere usata al posto di*args
per forzare i valori come argomenti della parola chiave senza fornire una lista di parametri variadici. Gli elenchi di parametri solo per parole chiave sono disponibili solo in Python 3.def func(a, b, *args, x, y): print(a, b, args, x, y) func(1, 2, 3, 4, x=5, y=6) #>>> 1, 2, (3, 4), 5, 6
def func(a, b, *, x, y): print(a, b, x, y) func(1, 2, x=5, y=6) #>>> 1, 2, 5, 6
**kwargs
deve arrivare per ultimo nell'elenco dei parametri.def test(**kwargs, *args): # File "<stdin>", line 1 # def test(**kwargs, *args): # ^ # SyntaxError: invalid syntax
Usare * args durante la scrittura di funzioni
Puoi usare la stella * quando scrivi una funzione per raccogliere tutti gli argomenti posizionali (cioè senza nome) in una tupla:
def print_args(farg, *args):
print("formal arg: %s" % farg)
for arg in args:
print("another positional arg: %s" % arg)
Metodo di chiamata:
print_args(1, "two", 3)
In questa chiamata, farg verrà assegnato come sempre, e gli altri due verranno inseriti nella tupla degli args, nell'ordine in cui sono stati ricevuti.
Usare ** kwargs durante la scrittura di funzioni
È possibile definire una funzione che accetta un numero arbitrario di argomenti di parole chiave (denominati) utilizzando la doppia stella **
prima del nome di un parametro:
def print_kwargs(**kwargs):
print(kwargs)
Quando chiama il metodo, Python costruirà un dizionario di tutti gli argomenti delle parole chiave e lo renderà disponibile nel corpo della funzione:
print_kwargs(a="two", b=3)
# prints: "{a: "two", b=3}"
Si noti che il parametro ** kwargs nella definizione della funzione deve sempre essere l'ultimo parametro e corrisponderà solo agli argomenti passati dopo quelli precedenti.
def example(a, **kw):
print kw
example(a=2, b=3, c=4) # => {'b': 3, 'c': 4}
All'interno del corpo della funzione, kwargs
viene manipolato allo stesso modo di un dizionario; per poter accedere ai singoli elementi in kwargs
fai semplicemente scorrere come faresti con un normale dizionario:
def print_kwargs(**kwargs):
for key in kwargs:
print("key = {0}, value = {1}".format(key, kwargs[key]))
Ora, chiamando print_kwargs(a="two", b=1)
mostra il seguente output:
print_kwargs(a = "two", b = 1)
key = a, value = "two"
key = b, value = 1
Usare * args quando si chiamano le funzioni
Un caso di uso comune per *args
in una definizione di funzione è delegare l'elaborazione a una funzione di tipo wrapper o ereditata. Un tipico esempio potrebbe essere nel metodo __init__
una classe
class A(object):
def __init__(self, b, c):
self.y = b
self.z = c
class B(A):
def __init__(self, a, *args, **kwargs):
super(B, self).__init__(*args, **kwargs)
self.x = a
Qui, il a
parametro viene elaborato dalla classe figlio dopo tutti gli altri argomenti (posizionali e parole chiave) sono passati su - ed elaborati dal - la classe di base.
Per esempio:
b = B(1, 2, 3)
b.x # 1
b.y # 2
b.z # 3
Quello che succede qui è la funzione di classe B
__init__
vede gli argomenti 1, 2, 3
. Sa che ha bisogno di prendere un argomento posizionale ( a
), quindi afferra il primo argomento passato in ( 1
), quindi nell'ambito della funzione a == 1
.
Successivamente, vede che è necessario prendere un numero arbitrario di argomenti posizionali ( *args
) in modo che tenga il resto degli argomenti posizionali passati in ( 1, 2
) e li inserisca in *args
. Ora (nell'ambito della funzione) args == [2, 3]
.
Quindi, chiama la funzione __init__
classe A
con *args
. Python vede *
di fronte a arg e "decomprime" la lista in argomenti. In questo esempio, quando la classe B
's __init__
funzione chiama classe A
' s __init__
funzione, ma passa gli argomenti 2, 3
(cioè A(2, 3)
).
Infine, imposta la propria proprietà x
sul primo argomento posizionale a
, che equivale a 1
.
Usare ** kwargs quando si chiamano le funzioni
È possibile utilizzare un dizionario per assegnare valori ai parametri della funzione; utilizzando i parametri nome come chiavi nel dizionario e il valore di questi argomenti associati a ogni chiave:
def test_func(arg1, arg2, arg3): # Usual function with three arguments
print("arg1: %s" % arg1)
print("arg2: %s" % arg2)
print("arg3: %s" % arg3)
# Note that dictionaries are unordered, so we can switch arg2 and arg3. Only the names matter.
kwargs = {"arg3": 3, "arg2": "two"}
# Bind the first argument (ie. arg1) to 1, and use the kwargs dictionary to bind the others
test_var_args_call(1, **kwargs)
Usare * args quando si chiamano le funzioni
L'effetto dell'utilizzo dell'operatore *
su un argomento quando si chiama una funzione è quello di decomprimere l'elenco o un argomento di tupla
def print_args(arg1, arg2):
print(str(arg1) + str(arg2))
a = [1,2]
b = tuple([3,4])
print_args(*a)
# 12
print_args(*b)
# 34
Si noti che la lunghezza dell'argomento speciale deve essere uguale al numero degli argomenti della funzione.
Un idioma python comune è quello di utilizzare l'operatore di disimballaggio *
con la funzione zip
per invertire i suoi effetti:
a = [1,3,5,7,9]
b = [2,4,6,8,10]
zipped = zip(a,b)
# [(1,2), (3,4), (5,6), (7,8), (9,10)]
zip(*zipped)
# (1,3,5,7,9), (2,4,6,8,10)
Argomenti richiesti solo per parola chiave e parola chiave
Python 3 consente di definire argomenti di funzione che possono essere assegnati solo da parole chiave, anche senza valori predefiniti. Questo viene fatto usando la stella * per consumare ulteriori parametri posizionali senza impostare i parametri della parola chiave. Tutti gli argomenti dopo * sono argomenti con parole chiave (cioè non posizionali). Si noti che se agli argomenti con parole chiave non viene assegnato un valore predefinito, sono comunque necessari quando si chiama la funzione.
def print_args(arg1, *args, keyword_required, keyword_only=True):
print("first positional arg: {}".format(arg1))
for arg in args:
print("another positional arg: {}".format(arg))
print("keyword_required value: {}".format(keyword_required))
print("keyword_only value: {}".format(keyword_only))
print(1, 2, 3, 4) # TypeError: print_args() missing 1 required keyword-only argument: 'keyword_required'
print(1, 2, 3, keyword_required=4)
# first positional arg: 1
# another positional arg: 2
# another positional arg: 3
# keyword_required value: 4
# keyword_only value: True
Popolazione dei valori di kwarg con un dizionario
def foobar(foo=None, bar=None):
return "{}{}".format(foo, bar)
values = {"foo": "foo", "bar": "bar"}
foobar(**values) # "foobar"
** kwargs e valori predefiniti
Per utilizzare i valori predefiniti con ** kwargs
def fun(**kwargs):
print kwargs.get('value', 0)
fun()
# print 0
fun(value=1)
# print 1