Utilizarea *args și **kwargs

Așa că am dificultăți cu conceptul de *args " și " **kwargs.

Până acum am învățat că:

  • *args = lista de argumente - ca argumente poziționale
  • **kwargs = dicționar - ale cărui chei se separe de cuvinte cheie argumentele și valorile devin valori de aceste argumente.

Eu nu't înțeleagă ceea ce de programare sarcină acest lucru ar fi de ajutor.

Poate:

Cred că pentru a intra liste și dicționare ca argumente ale unei funcții ȘI în același timp ca un wildcard, deci nu pot trece NICI un argument?

Este un exemplu simplu pentru a explica cum *args " și " **kwargs sunt folosite?

De asemenea, tutorial am găsit folosit doar "*" și un nume de variabilă.

Sunt *args " și "**kwargs doar substituenți sau folosesti exact*args " și " **kwargs în codul?

Comentarii la întrebare (6)
Soluția

Sintaxa este * "și"**. Numele *args " și " **kwargs sunt numai de către convenție, dar nu's nici o cerință greu de a le folosi.

Ai folosi *args când're nu sunt sigur cât de multe argumente ar putea fi trecut la funcție, și anume permite să treci un număr arbitrar de argumente pentru funcție. De exemplu:

>>> def print_everything(*args):
        for count, thing in enumerate(args):
...         print( '{0}. {1}'.format(count, thing))
...
>>> print_everything('apple', 'banana', 'cabbage')
0. apple
1. banana
2. cabbage

În mod similar, **kwargs vă permite să se ocupe numit argumente care nu ați definit în avans:

>>> def table_things(**kwargs):
...     for name, value in kwargs.items():
...         print( '{0} = {1}'.format(name, value))
...
>>> table_things(apple = 'fruit', cabbage = 'vegetable')
cabbage = vegetable
apple = fruit

Puteți folosi aceste, împreună cu nume de argumente prea. Explicit argumentele obține valori mai întâi și apoi totul altceva este trecut la *args " și " **kwargs. Numit argumente vin primele în listă. De exemplu:

def table_things(titlestring, **kwargs)

Puteți folosi, de asemenea, ambele în aceeași funcție definiție, dar *args trebuie să aibă loc înainte de **kwargs.

Puteți folosi, de asemenea, * " și " * * sintaxă atunci când apelați o funcție. De exemplu:

>>> def print_three_things(a, b, c):
...     print( 'a = {0}, b = {1}, c = {2}'.format(a,b,c))
...
>>> mylist = ['aardvark', 'baboon', 'cat']
>>> print_three_things(*mylist)
a = aardvark, b = baboon, c = cat

După cum puteți vedea în acest caz este nevoie de lista (sau tuplu) de elemente și despachetați-l. Prin aceasta ea le potrivește cu argumente în funcție. Desigur, ai putea avea un " * " atât în definiția funcției și în apelul funcției.

Comentarii (7)

Un loc în cazul în care utilizarea de *args " și " **kwargs este destul de util este pentru subclasarea.

class Foo(object):
    def __init__(self, value1, value2):
        # do something with the values
        print value1, value2

class MyFoo(Foo):
    def __init__(self, *args, **kwargs):
        # do something else, don't care about the args
        print 'myfoo'
        super(MyFoo, self).__init__(*args, **kwargs)

În acest fel puteți extinde comportamentul Foo clasă, fără a fi nevoie să știe prea multe despre Foo. Acest lucru poate fi destul de convenabil dacă sunteți programare la un API care s-ar putea schimba. MyFoo trece toate argumentele la Foo clasa.

Comentarii (8)

Aici's un exemplu care folosește 3 tipuri diferite de parametri.

def func(required_arg, *args, **kwargs):
    # required_arg is a positional-only parameter.
    print required_arg

    # args is a tuple of positional arguments,
    # because the parameter name has * prepended.
    if args: # If args is not empty.
        print args

    # kwargs is a dictionary of keyword arguments,
    # because the parameter name has ** prepended.
    if kwargs: # If kwargs is not empty.
        print kwargs

>>> func()
Traceback (most recent call last):
  File "", line 1, in 
TypeError: func() takes at least 1 argument (0 given)

>>> func("required argument")
required argument

>>> func("required argument", 1, 2, '3')
required argument
(1, 2, '3')

>>> func("required argument", 1, 2, '3', keyword1=4, keyword2="foo")
required argument
(1, 2, '3')
{'keyword2': 'foo', 'keyword1': 4}
Comentarii (0)

Aici's unul din locurile mele preferate pentru a utiliza ** sintaxă ca și în Dave Webb's ultim exemplu:

mynum = 1000
mystr = 'Hello World!'
print "{mystr} New-style formatting is {mynum}x more fun!".format(**locals())

Am'm nu-s sigur dacă-l's foarte repede în comparație cu folosind doar numele ei înșiși, dar's mult mai ușor să tastați!

Comentarii (8)

Un caz în care *args și **kwargs sunt utile când este scris înveliș funcții (cum ar fi decoratori) care trebuie să fie capabil de a accepta argumente arbitrare de a trece prin funcția de a fi împachetate. De exemplu, un simplu decorator care imprimă argumente și întoarce valoarea funcției fiind înfășurat:

def mydecorator( f ):
   @functools.wraps( f )
   def wrapper( *args, **kwargs ):
      print "Calling f", args, kwargs
      v = f( *args, **kwargs )
      print "f returned", v
      return v
   return wrapper
Comentarii (0)

*args și **kwargs sunt speciale-magic caracteristici de Python. Cred că de o funcție care ar putea avea un număr necunoscut de argumente. De exemplu, pentru orice motive, doriți să aveți funcție care însumează un număr necunoscut de numere (și nu't doriți să utilizați built-in funcție de sumă). Deci, vă scriu această funcție:

def sumFunction(*args):
  result = 0
  for x in args:
    result += x
  return result

și să-l utilizați, cum ar fi: sumFunction(3,4,6,3,6,8,9).

kwargs are diferite funcții. Cu kwargs puteți da arbitrare de cuvinte cheie argumente pentru o funcție și le puteți accesa ca un dictonary.

def someFunction(**kwargs):
  if 'text' in kwargs:
    print kwargs['text']

De asteptare someFunction(text="foo") va imprima foo.

Comentarii (0)

Doar imaginați-vă că aveți o funcție, dar nu't vreau să limiteze numărul de parametri este nevoie. Exemplu:

>>> import operator
>>> def multiply(*args):
...  return reduce(operator.mul, args)

Apoi, utilizați această funcție, cum ar fi:

>>> multiply(1,2,3)
6

or

>>> numbers = [1,2,3]
>>> multiply(*numbers)
6
Comentarii (0)

Numele *args " și "**kwargs " sau " **kw sunt pur prin convenție. Ea face mai ușor pentru noi să citim reciproc's cod

Un loc este la îndemână, este atunci când se utilizează struct module

struct.despachetați() returnează un tuplu întrucât struct.pack() utilizează un număr variabil de argumente. Atunci când manipularea datelor este convenabil pentru a fi capabil să treacă un tuplu pentru a lovit.pack() eg.

tuple_of_data = struct.unpack(format_str, data)
... manipulate the data
new_data = struct.pack(format_str, *tuple_of_data)

fără această abilitate te-ar fi obligat să scrie

new_data = struct.pack(format_str, tuple_of_data[0], tuple_of_data[1], tuple_of_data[2],...)

ceea ce înseamnă, de asemenea, dacă format_str modificările și dimensiunea tuplu schimbări, am'll trebuie să meargă înapoi și edita foarte lung de linie

Comentarii (0)

Rețineți că *args/*kwargs este parte a funcției-de asteptare sintaxă, și nu într-adevăr un operator. Acest lucru are un anumit efect secundar care m-am întâlnit, care este că puteți't de a folosi args de expansiune cu declarația de imprimare, de imprimare nu este o funcție.

Acest lucru pare rezonabil:

def myprint(*args):
    print *args

Din păcate, aceasta nu't compila (eroare de sintaxă).

Aceasta compilează:

def myprint(*args):
    print args

Dar imprimă argumente ca un tuplu, care e't ceea ce ne dorim.

Aceasta este soluția pe care am stabilit pe:

def myprint(*args):
    for arg in args:
        print arg,
    print
Comentarii (2)

Acești parametri sunt de obicei folosite pentru proxy funcții, astfel încât proxy poate trece orice parametru de intrare pentru funcția țintă.

def foo(bar=2, baz=5):
    print bar, baz

def proxy(x, *args, **kwargs): # reqire parameter x and accept any number of additional arguments
    print x
    foo(*args, **kwargs) # applies the "non-x" parameter to foo

proxy(23, 5, baz='foo') # calls foo with bar=5 and baz=foo
proxy(6)# calls foo with its default arguments
proxy(7, bar='asdas') # calls foo with bar='asdas' and leave baz default argument

Dar când acești parametri ascunde real parametru numele, este mai bine pentru a le evita.

Comentarii (0)

Puteți avea o privire la python-docs (docs.python.org în FAQ), dar mai ales pentru o bună explicație misterioasa domnișoară args și domnul kwargs (curtoazie de archive.org) (original, mort link-ul este aici).

Într-un cuvânt, ambele sunt utilizate atunci când parametrii opționali pentru o funcție sau metodă sunt folosite. Cum spune Dave, *args este utilizat atunci când nu't știu cât de multe argumente ar putea fi trecut, și **kwargs atunci când doriți să se ocupe de parametri specificate prin nume și valoare, ca în:

myfunction(myarg=1)
Comentarii (2)