Frage * Argumente und ** Kwargs? [Duplikat]


Diese Frage hat hier bereits eine Antwort:

So habe ich Schwierigkeiten mit dem Konzept von *args und **kwargs.

Bisher habe ich gelernt, dass:

  • *args = Liste der Argumente - als Positionsargumente
  • **kwargs = Dictionary - deren Schlüssel werden zu separaten Schlüsselwortargumenten und die Werte werden zu Werten dieser Argumente.

Ich verstehe nicht, für welche Programmieraufgabe das hilfreich wäre.

Könnte sein:

Ich denke, Listen und Wörterbücher als Argumente einer Funktion und gleichzeitig als Platzhalter einzugeben, damit ich jedes Argument bestehen kann?

Gibt es ein einfaches Beispiel, um zu erklären, wie *args und **kwargs werden verwendet?

Auch das Tutorial fand ich nur mit dem "*" und einem Variablennamen.

Sind *args und **kwargs nur Platzhalter oder verwenden Sie genau *args und **kwargs im Code?


1189
2017-08-03 08:28


Ursprung


Antworten:


Die Syntax ist die * und **. Die Namen *args und **kwargs sind nur per Konvention, aber es gibt keine harte Voraussetzung, sie zu verwenden.

Du würdest es benutzen *args wenn Sie nicht sicher sind, wie viele Argumente an Ihre Funktion übergeben werden können, d. h. Sie können eine beliebige Anzahl von Argumenten an Ihre Funktion übergeben. Beispielsweise:

>>> 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

Ähnlich, **kwargs erlaubt Ihnen, benannte Argumente zu behandeln, die Sie nicht im Voraus definiert haben:

>>> 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

Sie können diese auch zusammen mit benannten Argumenten verwenden. Die expliziten Argumente erhalten zuerst Werte und dann wird alles andere übergeben *args und **kwargs. Die benannten Argumente stehen in der Liste an erster Stelle. Beispielsweise:

def table_things(titlestring, **kwargs)

Sie können auch beide in der gleichen Funktionsdefinition aber verwenden *args muss vorher vorkommen **kwargs.

Sie können auch die * und ** Syntax beim Aufruf einer Funktion. Beispielsweise:

>>> 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

Wie Sie in diesem Fall sehen können, nimmt es die Liste (oder das Tupel) der Elemente und entpackt sie. Dadurch werden sie mit den Argumenten in der Funktion abgeglichen. Natürlich könntest du eine haben * sowohl in der Funktionsdefinition als auch im Funktionsaufruf.


1472
2017-08-03 08:38



Ein Ort, wo die Verwendung von *args und **kwargs ist sehr nützlich für Unterklassen.

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)

Auf diese Weise können Sie das Verhalten der Foo-Klasse erweitern, ohne zu viel über Foo wissen zu müssen. Dies kann sehr praktisch sein, wenn Sie eine API programmieren, die sich ändern könnte. MyFoo übergibt einfach alle Argumente an die Foo-Klasse.


442
2017-08-03 08:39



Hier ist ein Beispiel, das 3 verschiedene Arten von Parametern verwendet.

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 "<stdin>", line 1, in <module>
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}

278
2017-08-03 08:42



Hier ist einer meiner Lieblingsorte, um den zu benutzen ** Syntax wie im letzten Beispiel von Dave Webb:

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

Ich bin mir nicht sicher, ob es im Vergleich zu den Namen selbst schrecklich schnell ist, aber es ist viel einfacher zu tippen!


65
2017-08-03 13:03



Ein Fall, in dem * args und ** kwargs nützlich sind, ist beim Schreiben von Wrapper-Funktionen (z. B. Dekoratoren), die in der Lage sein müssen, beliebige Argumente zu akzeptieren, die an die zu umwickelnde Funktion übergeben werden. Zum Beispiel ein einfacher Decorator, der die Argumente und den Rückgabewert der umbrochenen Funktion ausgibt:

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

39
2017-08-03 08:40



* args und ** kwargs sind spezielle magische Eigenschaften von Python. Stellen Sie sich eine Funktion vor, die eine unbekannte Anzahl von Argumenten haben könnte. Zum Beispiel möchten Sie, aus welchen Gründen auch immer, eine Funktion haben, die eine unbekannte Anzahl von Zahlen summiert (und Sie möchten nicht die eingebaute Summenfunktion verwenden). Also schreibst du diese Funktion:

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

und benutze es wie: sumFunction (3,4,6,3,6,8,9).

** Kwargs hat eine unterschiedliche Funktion. Mit ** kwargs können Sie einer Funktion beliebige Schlüsselwortargumente geben und Sie können sie als Diktat verwenden.

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

Durch den Aufruf von someFunction (text = "foo") wird foo gedruckt.


35
2017-08-03 08:40



Stellen Sie sich vor, Sie haben eine Funktion, aber Sie möchten die Anzahl der Parameter nicht einschränken. Beispiel:

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

Dann verwenden Sie diese Funktion wie:

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

or

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

17
2017-08-03 08:40



Die Namen *args und **kwargs oder **kw sind rein durch Konvention. Es erleichtert es uns, den Code des jeweils anderen zu lesen

Ein Ort ist es praktisch, wenn Sie das Strukturmodul verwenden

struct.unpack() gibt ein Tupel zurück, während struct.pack() verwendet eine variable Anzahl von Argumenten. Wenn Daten manipuliert werden, ist es praktisch, ein Tupel zu übergeben struck.pack() z.B.

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

Ohne diese Fähigkeit wären Sie gezwungen zu schreiben

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

Das bedeutet auch, wenn sich format_str ändert und sich die Größe des Tupels ändert, muss ich zurückgehen und diese wirklich lange Zeile bearbeiten


14
2017-08-03 08:32



Beachten Sie, dass * args / ** kwargs Teil der funktionsaufrufenden Syntax und nicht wirklich ein Operator ist. Dies hat einen besonderen Nebeneffekt, den ich kennengelernt habe, nämlich dass Sie keine * args-Erweiterung mit der print-Anweisung verwenden können, da print keine Funktion ist.

Dies scheint vernünftig zu sein:

def myprint(*args):
    print *args

Leider kompiliert es nicht (Syntaxfehler).

Dies kompiliert:

def myprint(*args):
    print args

Aber druckt die Argumente als Tupel, was wir nicht wollen.

Das ist die Lösung, auf die ich mich eingelassen habe:

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

9
2017-11-10 21:07



Diese Parameter werden normalerweise für Proxy-Funktionen verwendet, sodass der Proxy beliebige Eingabeparameter an die Zielfunktion übergeben kann.

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

Da diese Parameter jedoch die eigentlichen Parameternamen verbergen, ist es besser, sie zu vermeiden.


7
2017-08-03 08:41



Sie können sich die Python-Dokumente ansehen (docs.python.org in den FAQ), aber genauer gesagt für eine gute Erklärung die mysteriösen Miss Args und Mister Kwargs (mit freundlicher Genehmigung von archive.org) (Der ursprüngliche, tote Link ist Hier).

Kurz gesagt, beide werden verwendet, wenn optionale Parameter für eine Funktion oder Methode verwendet werden. Wie Dave sagt, wird * args verwendet, wenn Sie nicht wissen, wie viele Argumente übergeben werden können, und ** kwargs, wenn Sie Parameter verarbeiten möchten, die durch name und value wie folgt angegeben werden:

myfunction(myarg=1)

3
2017-08-03 08:40