webentwicklung-frage-antwort-db.com.de

Verwendung von * args und ** kwargs

Also 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 dies hilfreich wäre.

Vielleicht:

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

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

Auch das Tutorial, das ich gefunden habe, verwendete nur das "*" und einen Variablennamen.

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

1340
MacPython

Die Syntax lautet * und ** . Die Namen *args und **kwargs sind nur vereinbarungsgemäß, es besteht jedoch keine zwingende Notwendigkeit, sie zu verwenden.

Sie würden *args verwenden, wenn Sie nicht sicher sind, wie viele Argumente an Ihre Funktion übergeben werden können, d. H. Wenn Sie eine beliebige Anzahl von Argumenten an Ihre Funktion übergeben können. Zum Beispiel:

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

Auf ähnliche Weise können Sie mit **kwargs benannte Argumente 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 an *args und **kwargs übergeben. Die genannten Argumente stehen in der Liste an erster Stelle. Zum Beispiel:

def table_things(titlestring, **kwargs)

Sie können auch beide in derselben Funktionsdefinition verwenden, aber *args muss vor **kwargs auftreten.

Sie können beim Aufrufen einer Funktion auch die Syntax * und ** verwenden. Zum Beispiel:

>>> 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 Tupel) der Elemente und entpackt sie. Dadurch werden sie den Argumenten in der Funktion zugeordnet. Natürlich können Sie sowohl in der Funktionsdefinition als auch im Funktionsaufruf einen * haben.

1610
Dave Webb

Ein Ort, an dem die Verwendung von *args und **kwargs sehr nützlich ist, ist die Unterklasse.

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 möglicherweise ändert. MyFoo übergibt einfach alle Argumente an die Foo-Klasse.

470
Mark van Lent

Hier ist ein Beispiel, das drei 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}
306
Kit

Hier ist einer meiner Lieblingsorte, um die ** -Syntax wie im letzten Beispiel von Dave Webb zu verwenden:

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

Ich bin mir nicht sicher, ob es schrecklich schnell ist, wenn man es nur mit den Namen selbst vergleicht, aber es ist viel einfacher zu tippen!

71
Wayne Werner

Ein Fall, in dem * args und ** kwargs nützlich sind, ist das Schreiben von Wrapper-Funktionen (z. B. Dekoratoren), die beliebige Argumente akzeptieren müssen, um an die zu verpackende Funktion weitergeleitet zu werden. Zum Beispiel ein einfacher Dekorator, der die Argumente und den Rückgabewert der umschlossenen 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
43
jchl

* args und ** kwargs sind magische Besonderheiten von Python. Stellen Sie sich eine Funktion vor, die eine unbekannte Anzahl von Argumenten haben könnte. Aus welchen Gründen auch immer möchten Sie beispielsweise eine Funktion haben, die eine unbekannte Anzahl von Zahlen summiert (und Sie möchten die integrierte Summenfunktion nicht verwenden). So schreiben Sie diese Funktion:

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

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

** kwargs hat eine andere Funktion. Mit ** kwargs können Sie einer Funktion beliebige Schlüsselwortargumente zuweisen und als Dikton auf sie zugreifen.

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

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

36
Steven Mohr

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

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

Dann nutzen Sie diese Funktion wie folgt:

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

or

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

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

Ein nützlicher Ort ist die Verwendung des struct-Moduls

struct.unpack() gibt ein Tupel zurück, während struct.pack() eine variable Anzahl von Argumenten verwendet. Bei der Manipulation von Daten ist es zweckmäßig, ein Tupel an struck.pack() übergeben zu können, z.

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 heißt auch, wenn sich die format_str ändert und sich die Größe des Tupels ändert, muss ich diese wirklich lange Zeile bearbeiten

16
John La Rooy

Beachten Sie, dass * args/** kwargs Teil der Funktionsaufrufsyntax ist und nicht wirklich ein Operator. Dies hat einen besonderen Nebeneffekt, auf den ich gestoßen bin, nämlich, dass Sie die * args-Erweiterung nicht mit der print-Anweisung verwenden können, da print keine Funktion ist.

Das scheint vernünftig:

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.

Dies ist die Lösung, für die ich mich entschieden habe:

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

Diese Parameter werden normalerweise für Proxy-Funktionen verwendet, sodass der Proxy einen beliebigen 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 tatsächlichen Parameternamen verbergen, ist es besser, sie zu vermeiden.

7
Rudi

Sie können sich python docs (docs.python.org in den FAQ) ansehen, aber genauer gesagt, um eine gute Erklärung zu finden 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 dürfen.

myfunction(myarg=1)
3
Yoni H