it-swarm.com.de

Was bedeuten * args und ** kwargs?

Was genau macht *args und **kwargs bedeuten?

Laut der Dokumentation zu Python, so wie es scheint, wird ein Tupel von Argumenten übergeben.

def foo(hello, *args):
    print hello

    for each in args:
        print each

if __== '__main__':
    foo("LOVE", ["lol", "lololol"])

Dies druckt aus:

LOVE
['lol', 'lololol']

Wie setzen Sie sie effektiv ein?

263
UberJumper

Putting *args und/oder **kwargs als letztes Element in der Argumentliste Ihrer Funktionsdefinition erlaubt es dieser Funktion, eine beliebige Anzahl von Argumenten und/oder Schlüsselwortargumenten zu akzeptieren.

Wenn Sie beispielsweise eine Funktion schreiben möchten, die die Summe aller ihrer Argumente zurückgibt, unabhängig davon, wie viele Sie angeben, können Sie sie folgendermaßen schreiben:

def my_sum(*args):
    return sum(args)

Es wird wahrscheinlich häufiger in der objektorientierten Programmierung verwendet, wenn Sie eine Funktion überschreiben und die ursprüngliche Funktion mit den Argumenten aufrufen möchten, die der Benutzer übergibt.

Sie müssen sie nicht unbedingt args und kwargs nennen, das ist nur eine Konvention. Es ist das * und ** das macht die Magie.

Die offizielle Python Dokumentation hat einen tieferen Einblick .

249
Paul D. Waite

Sie werden auch zum Verwalten der Vererbung verwendet.

class Super( object ):
   def __init__( self, this, that ):
       self.this = this
       self.that = that

class Sub( Super ):
   def __init__( self, myStuff, *args, **kw ):
       super( Sub, self ).__init__( *args, **kw )
       self.myStuff= myStuff

x= Super( 2.7, 3.1 )
y= Sub( "green", 7, 6 )

Auf diese Weise weiß Sub nicht wirklich (oder interessiert sich nicht), was die Superklasse-Initialisierung ist. Wenn Sie feststellen, dass Sie die Superklasse ändern müssen, können Sie Fehler beheben, ohne die Details in den einzelnen Unterklassen zu ändern.

89
S.Lott

Beachten Sie die coole Sache in S.Lotts Kommentar - Sie können Funktionen auch mit *mylist Und **mydict Aufrufen, um Positions- und Schlüsselwortargumente zu entpacken:

def foo(a, b, c, d):
  print a, b, c, d

l = [0, 1]
d = {"d":3, "c":2}

foo(*l, **d)

Wird drucken: 0 1 2 3

66
orip

Eine weitere gute Verwendung für *args und **kwargs: Sie können generische "catch all" -Funktionen definieren. Dies ist ideal für Dekorateure, bei denen Sie einen solchen Wrapper anstelle der ursprünglichen Funktion zurückgeben.

Ein Beispiel mit einem Trivial Caching Decorator:

import pickle, functools
def cache(f):
  _cache = {}
  def wrapper(*args, **kwargs):
    key = pickle.dumps((args, kwargs))
    if key not in _cache:
      _cache[key] = f(*args, **kwargs) # call the wrapped function, save in cache
    return _cache[key] # read value from cache
  functools.update_wrapper(wrapper, f) # update wrapper's metadata
  return wrapper

import time
@cache
def foo(n):
  time.sleep(2)
  return n*2

foo(10) # first call with parameter 10, sleeps
foo(10) # returns immediately
25
orip

Nur um zu klären, wie Sie die Argumente entpacken und fehlende Argumente beseitigen können.

def func(**keyword_args):
  #-->keyword_args is a dictionary
  print 'func:'
  print keyword_args
  if keyword_args.has_key('b'): print keyword_args['b']
  if keyword_args.has_key('c'): print keyword_args['c']

def func2(*positional_args):
  #-->positional_args is a Tuple
  print 'func2:'
  print positional_args
  if len(positional_args) > 1:
    print positional_args[1]

def func3(*positional_args, **keyword_args):
  #It is an error to switch the order ie. def func3(**keyword_args, *positional_args):
  print 'func3:'
  print positional_args
  print keyword_args

func(a='Apple',b='banana')
func(c='candle')
func2('Apple','banana')#It is an error to do func2(a='Apple',b='banana')
func3('Apple','banana',a='Apple',b='banana')
func3('Apple',b='banana')#It is an error to do func3(b='banana','Apple')
17
Kaushik Ghose