python kwargs - Che cosa fanno **(stella doppia / asterisco)e *(asterisco / asterisco)per i parametri?




star operator (16)

Un buon esempio di utilizzo di entrambi in una funzione è:

>>> def foo(*arg,**kwargs):
...     print arg
...     print kwargs
>>>
>>> a = (1, 2, 3)
>>> b = {'aa': 11, 'bb': 22}
>>>
>>>
>>> foo(*a,**b)
(1, 2, 3)
{'aa': 11, 'bb': 22}
>>>
>>>
>>> foo(a,**b) 
((1, 2, 3),)
{'aa': 11, 'bb': 22}
>>>
>>>
>>> foo(a,b) 
((1, 2, 3), {'aa': 11, 'bb': 22})
{}
>>>
>>>
>>> foo(a,*b)
((1, 2, 3), 'aa', 'bb')
{}

Nelle seguenti definizioni di metodo, cosa fanno * e ** per param2 ?

def foo(param1, *param2):
def bar(param1, **param2):

Voglio dare un esempio che altri non hanno menzionato

* può anche decomprimere un generatore

Un esempio dal documento Python3

x = [1, 2, 3]
y = [4, 5, 6]

unzip_x, unzip_y = zip(*zip(x, y))

unzip_x sarà [1, 2, 3], unzip_y sarà [4, 5, 6]

Lo zip () riceve più argomenti irable e restituisce un generatore.

zip(*zip(x,y)) -> zip((1, 4), (2, 5), (3, 6))

Dalla documentazione di Python:

Se ci sono più argomenti posizionali di quanti sono gli slot dei parametri formali, viene sollevata un'eccezione TypeError, a meno che non sia presente un parametro formale che utilizza la sintassi "* identificatore"; in questo caso, quel parametro formale riceve una tupla contenente gli argomenti posizionali in eccesso (o una tupla vuota se non ci sono argomenti posizionali in eccesso).

Se un argomento parola chiave non corrisponde a un nome di parametro formale, viene sollevata un'eccezione TypeError, a meno che non sia presente un parametro formale che utilizza la sintassi "** identificatore"; in questo caso, quel parametro formale riceve un dizionario contenente gli argomenti di parole chiave in eccesso (utilizzando le parole chiave come chiavi e i valori dell'argomento come valori corrispondenti) o un (nuovo) dizionario vuoto se non ci sono argomenti di parole chiave in eccesso.


*args e **kwargs : consentono di passare un numero variabile di argomenti a una funzione.

*args : è usato per inviare alla funzione una lista di argomenti di lunghezza variabile senza parole chiave:

def args(normal_arg, *argv):
    print ("normal argument:",normal_arg)

    for arg in argv:
        print("Argument in list of arguments from *argv:", arg)

args('animals','fish','duck','bird')

Produrrà:

normal argument: animals
Argument in list of arguments from *argv: fish
Argument in list of arguments from *argv: duck
Argument in list of arguments from *argv: bird

**kwargs*

**kwargs consente di passare una lunghezza variabile di argomenti con parole chiave a una funzione. Dovresti usare **kwargs se vuoi gestire gli argomenti con nome in una funzione.

def who(**kwargs):
    if kwargs is not None:
        for key, value in kwargs.items():
            print ("Your %s is %s." %(key,value))

who (name="Nikola", last_name="Tesla", birthday = "7.10.1856", birthplace = "Croatia")  

Produrrà:

Your name is Nikola.
Your last_name is Tesla.
Your birthday is 7.10.1856.
Your birthplace is Croatia.

* significa ricevere argomenti variabili come lista

** significa ricevere argomenti variabili come dizionario

Usato come il seguente:

1) singolo *

def foo(*args):
    for arg in args:
        print(arg)

foo("two", 3)

Produzione:

two
3

2) Ora **

def bar(**kwargs):
    for key in kwargs:
        print(key, kwargs[key])

bar(dic1="two", dic2=3)

Produzione:

dic1 two
dic2 3

Cosa fa ** (stella doppia) e * (stella) per i parametri

Consentono di definire le funzioni da accettare e per consentire agli utenti di passare qualsiasi numero di argomenti, posizionale ( * ) e parola chiave ( ** ).

Definizione di funzioni

*args consente qualsiasi numero di argomenti posizionali opzionali (parametri), che saranno assegnati ad una tupla chiamata args .

**kwargs consente qualsiasi numero di argomenti di parole chiave opzionali (parametri), che saranno in un dt denominato kwargs .

Puoi (e dovresti) scegliere un nome appropriato, ma se l'intenzione è che gli argomenti siano di semantica non specifica, args e kwargs sono nomi standard.

Espansione, passando un numero qualsiasi di argomenti

Puoi anche usare *args e **kwargs per passare in parametri da liste (o qualsiasi iterable) e dicts (o qualsiasi mapping), rispettivamente.

La funzione che riceve i parametri non deve sapere che sono stati espansi.

Ad esempio, xrange di Python 2 non prevede esplicitamente *args , ma dal momento che prende 3 interi come argomenti:

>>> x = xrange(3) # create our *args - an iterable of 3 integers
>>> xrange(*x)    # expand here
xrange(0, 2, 2)

Come altro esempio, possiamo usare l'espansione dict in str.format :

>>> foo = 'FOO'
>>> bar = 'BAR'
>>> 'this is foo, {foo} and bar, {bar}'.format(**locals())
'this is foo, FOO and bar, BAR'

Novità in Python 3: definizione delle funzioni con argomenti solo parole chiave

Puoi avere argomenti con parole chiave solo dopo il *args - per esempio, qui, kwarg2 deve essere dato come argomento della parola chiave - non in modo posizionale:

def foo(arg, kwarg=None, *args, kwarg2=None, **kwargs): 
    return arg, kwarg, args, kwarg2, kwargs

Uso:

>>> foo(1,2,3,4,5,kwarg2='kwarg2', bar='bar', baz='baz')
(1, 2, (3, 4, 5), 'kwarg2', {'bar': 'bar', 'baz': 'baz'})

Inoltre, * può essere usato da solo per indicare che seguono solo argomenti con parole chiave, senza consentire argomenti posizionali illimitati.

def foo(arg, kwarg=None, *, kwarg2=None, **kwargs): 
    return arg, kwarg, kwarg2, kwargs

Qui, ancora una volta kwarg2 deve essere un argomento di parole chiave con nome esplicito:

>>> foo(1,2,kwarg2='kwarg2', foo='foo', bar='bar')
(1, 2, 'kwarg2', {'foo': 'foo', 'bar': 'bar'})

E non possiamo più accettare argomenti posizionali illimitati perché non abbiamo *args* :

>>> foo(1,2,3,4,5, kwarg2='kwarg2', foo='foo', bar='bar')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: foo() takes from 1 to 2 positional arguments 
    but 5 positional arguments (and 1 keyword-only argument) were given

Ancora una volta, più semplicemente, qui richiediamo che kwarg sia dato per nome, non in posizione:

def bar(*, kwarg=None): 
    return kwarg

In questo esempio, vediamo che se proviamo a passare kwarg posizione, otteniamo un errore:

>>> bar('kwarg')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: bar() takes 0 positional arguments but 1 was given

Dobbiamo passare esplicitamente il parametro kwarg come argomento della parola chiave.

>>> bar(kwarg='kwarg')
'kwarg'

Demo compatibili con Python 2

*args (tipicamente detto "star-args") e **kwargs (le stelle possono essere implicite dicendo "kwargs", ma essere esplicite con "double-star kwargs") sono idiomi comuni di Python per usare la notazione * e ** . Questi specifici nomi di variabili non sono richiesti (ad esempio potresti usare *foos e **bars ), ma un allontanamento dalla convenzione rischia di far arrabbiare i tuoi colleghi coder Python.

Generalmente li usiamo quando non sappiamo quale sarà la nostra funzione o quanti argomenti possiamo passare, e talvolta anche nominando ogni variabile separatamente risulterebbe molto disordinata e ridondante (ma questo è un caso in cui solitamente è esplicito meglio di implicito).

Esempio 1

La seguente funzione descrive come possono essere utilizzati e dimostra il comportamento. Si noti che l'argomento b nome verrà utilizzato dal secondo argomento posizionale prima:

def foo(a, b=10, *args, **kwargs):
    '''
    this function takes required argument a, not required keyword argument b
    and any number of unknown positional arguments and keyword arguments after
    '''
    print('a is a required argument, and its value is {0}'.format(a))
    print('b not required, its default value is 10, actual value: {0}'.format(b))
    # we can inspect the unknown arguments we were passed:
    #  - args:
    print('args is of type {0} and length {1}'.format(type(args), len(args)))
    for arg in args:
        print('unknown arg: {0}'.format(arg))
    #  - kwargs:
    print('kwargs is of type {0} and length {1}'.format(type(kwargs),
                                                        len(kwargs)))
    for kw, arg in kwargs.items():
        print('unknown kwarg - kw: {0}, arg: {1}'.format(kw, arg))
    # But we don't have to know anything about them 
    # to pass them to other functions.
    print('Args or kwargs can be passed without knowing what they are.')
    # max can take two or more positional args: max(a, b, c...)
    print('e.g. max(a, b, *args) \n{0}'.format(
      max(a, b, *args))) 
    kweg = 'dict({0})'.format( # named args same as unknown kwargs
      ', '.join('{k}={v}'.format(k=k, v=v) 
                             for k, v in sorted(kwargs.items())))
    print('e.g. dict(**kwargs) (same as {kweg}) returns: \n{0}'.format(
      dict(**kwargs), kweg=kweg))

Possiamo controllare l'aiuto online per la firma della funzione, con l' help(foo) , che ci dice

foo(a, b=10, *args, **kwargs)

Chiamiamo questa funzione con foo(1, 2, 3, 4, e=5, f=6, g=7)

che stampa:

a is a required argument, and its value is 1
b not required, its default value is 10, actual value: 2
args is of type <type 'tuple'> and length 2
unknown arg: 3
unknown arg: 4
kwargs is of type <type 'dict'> and length 3
unknown kwarg - kw: e, arg: 5
unknown kwarg - kw: g, arg: 7
unknown kwarg - kw: f, arg: 6
Args or kwargs can be passed without knowing what they are.
e.g. max(a, b, *args) 
4
e.g. dict(**kwargs) (same as dict(e=5, f=6, g=7)) returns: 
{'e': 5, 'g': 7, 'f': 6}

Esempio 2

Possiamo anche chiamarlo usando un'altra funzione, nella quale forniamo semplicemente a :

def bar(a):
    b, c, d, e, f = 2, 3, 4, 5, 6
    # dumping every local variable into foo as a keyword argument 
    # by expanding the locals dict:
    foo(**locals()) 

bar(100) stampa:

a is a required argument, and its value is 100
b not required, its default value is 10, actual value: 2
args is of type <type 'tuple'> and length 0
kwargs is of type <type 'dict'> and length 4
unknown kwarg - kw: c, arg: 3
unknown kwarg - kw: e, arg: 5
unknown kwarg - kw: d, arg: 4
unknown kwarg - kw: f, arg: 6
Args or kwargs can be passed without knowing what they are.
e.g. max(a, b, *args) 
100
e.g. dict(**kwargs) (same as dict(c=3, d=4, e=5, f=6)) returns: 
{'c': 3, 'e': 5, 'd': 4, 'f': 6}

Esempio 3: utilizzo pratico nei decoratori

OK, forse non stiamo ancora vedendo l'utilità. Quindi immagina di avere diverse funzioni con codice ridondante prima e / o dopo il codice di differenziazione. Le seguenti funzioni nominate sono solo pseudo-codice per scopi illustrativi.

def foo(a, b, c, d=0, e=100):
    # imagine this is much more code than a simple function call
    preprocess() 
    differentiating_process_foo(a,b,c,d,e)
    # imagine this is much more code than a simple function call
    postprocess()

def bar(a, b, c=None, d=0, e=100, f=None):
    preprocess()
    differentiating_process_bar(a,b,c,d,e,f)
    postprocess()

def baz(a, b, c, d, e, f):
    ... and so on

Potremmo essere in grado di gestirlo in modo diverso, ma possiamo certamente estrarre la ridondanza con un decoratore, e quindi il nostro esempio qui sotto dimostra come *args e **kwargs possono essere molto utili:

def decorator(function):
    '''function to wrap other functions with a pre- and postprocess'''
    @functools.wraps(function) # applies module, name, and docstring to wrapper
    def wrapper(*args, **kwargs):
        # again, imagine this is complicated, but we only write it once!
        preprocess()
        function(*args, **kwargs)
        postprocess()
    return wrapper

E ora ogni funzione avvolta può essere scritta in modo molto più succinto, come abbiamo calcolato la ridondanza:

@decorator
def foo(a, b, c, d=0, e=100):
    differentiating_process_foo(a,b,c,d,e)

@decorator
def bar(a, b, c=None, d=0, e=100, f=None):
    differentiating_process_bar(a,b,c,d,e,f)

@decorator
def baz(a, b, c=None, d=0, e=100, f=None, g=None):
    differentiating_process_baz(a,b,c,d,e,f, g)

@decorator
def quux(a, b, c=None, d=0, e=100, f=None, g=None, h=None):
    differentiating_process_quux(a,b,c,d,e,f,g,h)

E, calcolando il nostro codice, che *args e **kwargs ci consente di fare, riduciamo le linee di codice, miglioriamo la leggibilità e la manutenibilità, e abbiamo solo posizioni canoniche per la logica del nostro programma. Se abbiamo bisogno di cambiare qualsiasi parte di questa struttura, abbiamo un posto in cui fare ogni cambiamento.


* args = * aList = tutti gli elementi in una lista

** args = ** aDict = tutti gli elementi in un dett


  • def foo(param1, *param2): è un metodo in grado di accettare un numero arbitrario di valori per *param2 ,
  • def bar(param1, **param2): è un metodo che può accettare un numero arbitrario di valori con i tasti per *param2
  • param1 è un parametro semplice.

Ad esempio, la sintassi per l'implementazione di vararg in Java come segue:

accessModifier methodName(datatype… arg) {
    // method body
}

In Python 3.5, è anche possibile utilizzare questa sintassi in list , dict , tuple e set display (anche a volte chiamati letterali). Vedi PEP 488: generalizzazioni di disimballaggio aggiuntive .

>>> (0, *range(1, 4), 5, *range(6, 8))
(0, 1, 2, 3, 5, 6, 7)
>>> [0, *range(1, 4), 5, *range(6, 8)]
[0, 1, 2, 3, 5, 6, 7]
>>> {0, *range(1, 4), 5, *range(6, 8)}
{0, 1, 2, 3, 5, 6, 7}
>>> d = {'one': 1, 'two': 2, 'three': 3}
>>> e = {'six': 6, 'seven': 7}
>>> {'zero': 0, **d, 'five': 5, **e}
{'five': 5, 'seven': 7, 'two': 2, 'one': 1, 'three': 3, 'six': 6, 'zero': 0}

Consente inoltre di decomprimere più iterables in una singola chiamata di funzione.

>>> range(*[1, 10], *[2])
range(1, 10, 2)

(Grazie a mgilson per il collegamento PEP.)


Mentre gli usi per gli operatori star / splat sono stati expanded in Python 3, mi piace la seguente tabella in quanto riguarda l'uso di questi operatori con funzioni . Gli operatori di splat possono essere utilizzati sia nella costruzione della funzione che nella chiamata di funzione:

            In function *construction*      In function *call*
=======================================================================
          |  def f(*args):                 |  def f(a, b):
*args     |      for arg in args:          |      return a + b
          |          print(arg)            |  args = (1, 2)
          |  f(1, 2)                       |  f(*args)
----------|--------------------------------|---------------------------
          |  def f(a, b):                  |  def f(a, b):
**kwargs  |      return a + b              |      return a + b
          |  def g(**kwargs):              |  kwargs = dict(a=1, b=2)
          |      return f(**kwargs)        |  f(**kwargs)
          |  g(a=1, b=2)                   |
-----------------------------------------------------------------------

Questo in realtà serve solo a riassumere la answer Lorin Hochstein, ma la trovo utile.


Il singolo * significa che può esserci un numero qualsiasi di argomenti posizionali extra. foo() può essere invocato come foo(1,2,3,4,5) . Nel corpo di foo () param2 è una sequenza contenente 2-5.

Il doppio ** significa che può esserci un numero qualsiasi di parametri con nome extra. bar() può essere invocato come bar(1, a=2, b=3) . Nel corpo di bar () param2 è un dizionario contenente {'a': 2, 'b': 3}

Con il seguente codice:

def foo(param1, *param2):
    print param1
    print param2

def bar(param1, **param2):
    print param1
    print param2

foo(1,2,3,4,5)
bar(1,a=2,b=3)

l'output è

1
(2, 3, 4, 5)
1
{'a': 2, 'b': 3}

Vale anche la pena notare che è possibile usare * e ** quando si chiamano le funzioni. Questa è una scorciatoia che consente di passare più argomenti a una funzione direttamente usando una lista / tupla o un dizionario. Ad esempio, se hai la seguente funzione:

def foo(x,y,z):
    print("x=" + str(x))
    print("y=" + str(y))
    print("z=" + str(z))

Puoi fare cose come:

>>> mylist = [1,2,3]
>>> foo(*mylist)
x=1
y=2
z=3

>>> mydict = {'x':1,'y':2,'z':3}
>>> foo(**mydict)
x=1
y=2
z=3

>>> mytuple = (1, 2, 3)
>>> foo(*mytuple)
x=1
y=2
z=3

Nota: le chiavi in mydict devono essere denominate esattamente come i parametri della funzione foo . Altrimenti verrà TypeError un TypeError :

>>> mydict = {'x':1,'y':2,'z':3,'badnews':9}
>>> foo(**mydict)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: foo() got an unexpected keyword argument 'badnews'

Questo esempio ti aiuterà a ricordare *args , **kwargs e persino super ed ereditarietà in Python in una volta.

class base(object):
    def __init__(self, base_param):
        self.base_param = base_param


class child1(base): # inherited from base class
    def __init__(self, child_param, *args) # *args for non-keyword args
        self.child_param = child_param
        super(child1, self).__init__(*args) # call __init__ of the base class and initialize it with a NON-KEYWORD arg

class child2(base):
    def __init__(self, child_param, **kwargs):
        self.child_param = child_param
        super(child2, self).__init__(**kwargs) # call __init__ of the base class and initialize it with a KEYWORD arg

c1 = child1(1,0)
c2 = child2(1,base_param=0)
print c1.base_param # 0
print c1.child_param # 1
print c2.base_param # 0
print c2.child_param # 1

Per quelli di voi che imparano dagli esempi!

  1. Lo scopo di * è di darti la possibilità di definire una funzione che può prendere un numero arbitrario di argomenti forniti come lista (es. f(*myList) ).
  2. Lo scopo di ** è di darti la possibilità di alimentare gli argomenti di una funzione fornendo un dizionario (es. f(**{'x' : 1, 'y' : 2}) ).

Cerchiamo di mostrarlo definendo una funzione che prende due variabili normali x , y , e può accettare più argomenti come myArgs , e può accettare ancora più argomenti come myKW . Più tardi, mostreremo come nutrire y usando myArgDict .

def f(x, y, *myArgs, **myKW):
    print("# x      = {}".format(x))
    print("# y      = {}".format(y))
    print("# myArgs = {}".format(myArgs))
    print("# myKW   = {}".format(myKW))
    print("# ----------------------------------------------------------------------")

# Define a list for demonstration purposes
myList    = ["Left", "Right", "Up", "Down"]
# Define a dictionary for demonstration purposes
myDict    = {"Wubba": "lubba", "Dub": "dub"}
# Define a dictionary to feed y
myArgDict = {'y': "Why?", 'y0': "Why not?", "q": "Here is a cue!"}

# The 1st elem of myList feeds y
f("myEx", *myList, **myDict)
# x      = myEx
# y      = Left
# myArgs = ('Right', 'Up', 'Down')
# myKW   = {'Wubba': 'lubba', 'Dub': 'dub'}
# ----------------------------------------------------------------------

# y is matched and fed first
# The rest of myArgDict becomes additional arguments feeding myKW
f("myEx", **myArgDict)
# x      = myEx
# y      = Why?
# myArgs = ()
# myKW   = {'y0': 'Why not?', 'q': 'Here is a cue!'}
# ----------------------------------------------------------------------

# The rest of myArgDict becomes additional arguments feeding myArgs
f("myEx", *myArgDict)
# x      = myEx
# y      = y
# myArgs = ('y0', 'q')
# myKW   = {}
# ----------------------------------------------------------------------

# Feed extra arguments manually and append even more from my list
f("myEx", 4, 42, 420, *myList, *myDict, **myDict)
# x      = myEx
# y      = 4
# myArgs = (42, 420, 'Left', 'Right', 'Up', 'Down', 'Wubba', 'Dub')
# myKW   = {'Wubba': 'lubba', 'Dub': 'dub'}
# ----------------------------------------------------------------------

# Without the stars, the entire provided list and dict become x, and y:
f(myList, myDict)
# x      = ['Left', 'Right', 'Up', 'Down']
# y      = {'Wubba': 'lubba', 'Dub': 'dub'}
# myArgs = ()
# myKW   = {}
# ----------------------------------------------------------------------

Avvertenze

  1. ** è riservato esclusivamente ai dizionari.
  2. L'assegnazione di argomenti non opzionali avviene prima.
  3. Non è possibile utilizzare due volte un argomento non facoltativo.
  4. Se applicabile, ** deve venire dopo * , sempre.

Il *args e **kwargs è un linguaggio comune per consentire il numero arbitrario di argomenti per le funzioni come descritto nella sezione più sulla definizione delle funzioni nella documentazione di Python.

Il *args ti fornirà tutti i parametri di funzione come una tupla :

In [1]: def foo(*args):
   ...:     for a in args:
   ...:         print a
   ...:         
   ...:         

In [2]: foo(1)
1


In [4]: foo(1,2,3)
1
2
3

I **kwargs ti daranno tutti gli argomenti delle parole chiave tranne quelli corrispondenti a un parametro formale come dizionario.

In [5]: def bar(**kwargs):
   ...:     for a in kwargs:
   ...:         print a, kwargs[a]
   ...:         
   ...:         

In [6]: bar(name='one', age=27)
age 27
name one

Entrambi gli idiomi possono essere combinati con argomenti normali per consentire un insieme di argomenti fissi e alcuni argomenti variabili:

def foo(kind, *args, **kwargs):
   pass

Un altro uso dell'idioma *l è quello di scompattare gli elenchi di argomenti quando si chiama una funzione.

In [9]: def foo(bar, lee):
   ...:     print bar, lee
   ...:     
   ...:     

In [10]: l = [1,2]

In [11]: foo(*l)
1 2

In Python 3 è possibile usare *l sul lato sinistro di un compito ( Extended Iterable Unpacking ), sebbene fornisca una lista invece di una tupla in questo contesto:

first, *rest = [1,2,3,4]
first, *l, last = [1,2,3,4]

Anche Python 3 aggiunge una nuova semantica (si veda PEP 3102 ):

def func(arg1, arg2, arg3, *, kwarg1, kwarg2):
    pass

Tale funzione accetta solo 3 argomenti posizionali e tutto dopo * può essere passato solo come argomento della parola chiave.


se name == ' main ':

Vediamo se __name__ == '__main__':abbastanza spesso.

Controlla se un modulo viene importato o meno.

In altre parole, il codice all'interno del ifblocco verrà eseguito solo quando il codice viene eseguito direttamente. Qui directlysignifica not imported.

Vediamo cosa fa usando un semplice codice che stampa il nome del modulo:

# test.py
def test():
   print('test module name=%s' %(__name__))

if __name__ == '__main__':
   print('call test()')
   test()

Se eseguiamo direttamente il codice tramite python test.py, il nome del modulo è __main__:

call test()
test module name=__main__




python syntax parameter-passing identifier kwargs