2008-11-13 15 views
231

Was genau bedeuten *args und **kwargs?Was bedeuten * args und ** kwargs?

Nach der Python-Dokumentation, von was es scheint, übergibt es in einem Tupel von Argumenten.

def foo(hello, *args): 
    print hello 

    for each in args: 
     print each 

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

Dies gibt:

LOVE 
['lol', 'lololol'] 

Wie effektiv Sie sie nutzen?

+13

Nur ein schlechtes Wortspiel auf Stunden und Kilo - Stunden. – Mostlyharmless

+6

Dieser Artikel kann sehr nützlich für das Verständnis des Themas sein: http://agiliq.com/blog/2012/06/understanding-args-and-kwargs/ –

Antwort

225

Wenn Sie *args und/oder **kwargs als letzte Elemente in der Argumentliste der Funktionsdefinition einfügen, kann diese Funktion eine beliebige Anzahl von Argumenten und/oder Schlüsselwortargumenten akzeptieren.

Zum Beispiel, wenn Sie eine Funktion, die zurückgegeben die Summe aller seiner Argumente, egal wie viele Sie liefern, schreiben wollen könnte man es so schreiben:

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

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

Sie müssen sie nicht wirklich anrufen args und kwargs, das ist nur eine Konvention. Es ist die * und **, die die Magie machen.

Die offizielle Python-Dokumentation hat a more in-depth look.

+5

Kein Schweiß, du bist sehr willkommen. Verwirrt mich auch für eine Weile. Wenn Sie sich ernsthaft mit Python beschäftigen, würde ich 'Programming Python' von Mark Lutz wärmstens empfehlen. –

+39

Vielleicht Link zu dem Tutorial, das dies ausführlich erklärt, und sollte von jedem gelesen werden: http://docs.python.org/tutorial/controlflow.html#more-on-defining-functions –

+1

@AliAfshar: Ihr Link war alles Ich brauchte, hätte die Antwort selbst sein sollen. Vielen Dank! – scorpiodawg

82

Auch wir verwenden sie für die Verwaltung der Vererbung.

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 (wirklich) nicht, was die Superklasseninitialisierung ist. Wenn Sie erkennen, dass Sie die Superklasse ändern müssen, können Sie Dinge reparieren, ohne die Details in jeder Unterklasse schwitzen zu müssen.

+6

Dies ist eine der hilfreichsten Antworten, die ich gefunden habe, um 'super' zu benutzen. Diese Antwort ist mehr als 5 Jahre alt, aber ich denke, das ist immer noch eine großartige Möglichkeit, 'super' in Python 2.X zu verwenden, richtig? –

+0

Ja, immer noch der Weg, es zu tun. –

+0

Danke, aber es wäre toll, wenn Sie ein echtes Beispiel liefern könnten, warum und wann Sie es verwenden sollten. Im obigen Beispiel was passiert, wenn ich das anwende? – TaraGurung

63

Beachten Sie die coole Sache in S.Lott's comment - Sie arbeitet auch mit *mylist und **mydict auspacken Lage- und Schlüsselwort-Argumente nennen kann:

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

+0

Sie können auch '' mydict' (nicht '** mylist') tun, aber das Ergebnis wird etwas anders sein (und für manche unerwartet). – Tadeck

+1

einfach, prägnant und ein leicht zu folgen Beispiel, um den Punkt zu veranschaulichen. Meine Lieblingsantwort! – NickO

+0

@Tadeck Sie können '* x' für jedes iterable und' ** y' für jeden Mapping-Typ verwenden. Da ein Diktat sowohl ein iterables als auch ein Mapping ist, können Sie beides tun. Siehe auch http://stackoverflow.com/questions/8601268/python-class-that-acts-as-mapping-for-unpacking – augurar

24

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

Ein Beispiel mit einem trivialen Caching Dekorateur:

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 
15

Nur um zu klären, wie die Argumente entpacken, und der fehlenden Argumente kümmern usw.

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') 
Verwandte Themen