Was tun *args
und **kwargs
bedeuten?
def foo(x, y, *args):
def bar(x, y, **kwargs):
Todd
Was tun *args
und **kwargs
bedeuten?
def foo(x, y, *args):
def bar(x, y, **kwargs):
Peter Hofmann
Das *args
und **kwargs
ist eine gebräuchliche Redewendung, um eine beliebige Anzahl von Argumenten für Funktionen zuzulassen, wie im Abschnitt beschrieben mehr zum Definieren von Funktionen in der Python-Dokumentation.
Das *args
gibt Ihnen alle Funktionsparameter als Tupel:
def foo(*args):
for a in args:
print(a)
foo(1)
# 1
foo(1,2,3)
# 1
# 2
# 3
Das **kwargs
wird dir alles geben
Schlüsselwortargumente außer denen, die einem formalen Parameter wie einem Wörterbuch entsprechen.
def bar(**kwargs):
for a in kwargs:
print(a, kwargs[a])
bar(name="one", age=27)
# name one
# age 27
Beide Redewendungen können mit normalen Argumenten gemischt werden, um eine Reihe von festen und einigen variablen Argumenten zu ermöglichen:
def foo(kind, *args, **kwargs):
pass
Es ist auch möglich, dies umgekehrt zu verwenden:
def foo(a, b, c):
print(a, b, c)
obj = {'b':10, 'c':'lee'}
foo(100,**obj)
# 100 10 lee
Eine weitere Verwendung des *l
Redewendung ist zu Argumentlisten entpacken beim Aufruf einer Funktion.
def foo(bar, lee):
print(bar, lee)
l = [1,2]
foo(*l)
# 1 2
In Python 3 ist die Verwendung möglich *l
auf der linken Seite einer Zuweisung (Erweitertes iterables Entpacken), obwohl es in diesem Zusammenhang eine Liste anstelle eines Tupels gibt:
first, *rest = [1,2,3,4]
first, *l, last = [1,2,3,4]
Auch Python 3 fügt neue Semantik hinzu (vgl PEP 3102):
def func(arg1, arg2, arg3, *, kwarg1, kwarg2):
pass
Folgendes funktioniert beispielsweise in Python 3, aber nicht in Python 2:
>>> x = [1, 2]
>>> [*x]
[1, 2]
>>> [*x, 3, 4]
[1, 2, 3, 4]
>>> x = {1:1, 2:2}
>>> x
{1: 1, 2: 2}
>>> {**x, 3:3, 4:4}
{1: 1, 2: 2, 3: 3, 4: 4}
Eine solche Funktion akzeptiert nur 3 Positionsargumente und alles danach *
können nur als Schlüsselwortargumente übergeben werden.
dict
, die semantisch für die Übergabe von Schlüsselwortargumenten verwendet werden, sind willkürlich angeordnet. In Python 3.6 merken sich Schlüsselwortargumente jedoch garantiert die Einfügungsreihenfolge.**kwargs
entspricht jetzt der Reihenfolge, in der Schlüsselwortargumente an die Funktion übergeben wurden.” – Was ist neu in Python 3.6
Lorin Hochstein
Es ist auch erwähnenswert, dass Sie verwenden können *
und **
auch beim Aufruf von Funktionen. Dies ist eine Abkürzung, mit der Sie mehrere Argumente direkt an eine Funktion übergeben können, indem Sie entweder eine Liste/ein Tupel oder ein Wörterbuch verwenden. Wenn Sie beispielsweise die folgende Funktion haben:
def foo(x,y,z):
print("x=" + str(x))
print("y=" + str(y))
print("z=" + str(z))
Sie können Dinge tun wie:
>>> mylist = [1,2,3]
>>> foo(*mylist)
x=1
y=2
z=3
>>> mydict = {'x':1,'y':2,'z':3}
>>> foo(**mydict)
x=1
y=2
z=3
>>> mytuple = (1, 2, 3)
>>> foo(*mytuple)
x=1
y=2
z=3
Hinweis: Die Schlüssel in mydict
müssen genau wie die Parameter der Funktion benannt werden foo
. Andernfalls wirft es a TypeError
:
>>> mydict = {'x':1,'y':2,'z':3,'badnews':9}
>>> foo(**mydict)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: foo() got an unexpected keyword argument 'badnews'
nickd
Das einzelne * bedeutet, dass es beliebig viele zusätzliche Positionsargumente geben kann. foo()
kann wie aufgerufen werden foo(1,2,3,4,5)
. Im Hauptteil von foo() ist param2 eine Sequenz, die 2-5 enthält.
Das doppelte ** bedeutet, dass es eine beliebige Anzahl von zusätzlichen benannten Parametern geben kann. bar()
kann wie aufgerufen werden bar(1, a=2, b=3)
. Im Hauptteil von bar() ist param2 ein Wörterbuch, das {‘a’:2, ‘b’:3 } enthält.
Mit folgendem Code:
def foo(param1, *param2):
print(param1)
print(param2)
def bar(param1, **param2):
print(param1)
print(param2)
foo(1,2,3,4,5)
bar(1,a=2,b=3)
die Ausgabe ist
1
(2, 3, 4, 5)
1
{'a': 2, 'b': 3}
Russland muss Putin entfernen
Was macht
**
(Doppelstern) und*
(Stern) tun für Parameter?
Sie ermöglichen Funktionen, die definiert werden müssen, um akzeptiert zu werden und für Benutzer zu passieren beliebig viele Argumente, positional (*
) und Schlüsselwort (**
).
*args
erlaubt eine beliebige Anzahl optionaler Positionsargumente (Parameter), die einem Tupel namens zugewiesen werden args
.
**kwargs
erlaubt eine beliebige Anzahl optionaler Schlüsselwortargumente (Parameter), die in einem Diktat mit dem Namen enthalten sind kwargs
.
Sie können (und sollten) einen beliebigen geeigneten Namen wählen, aber wenn die Argumente eine unspezifische Semantik haben sollen, args
und kwargs
sind Standardnamen.
Sie können auch verwenden *args
und **kwargs
um Parameter aus Listen (oder iterierbaren) bzw. Diktaten (oder beliebigen Mappings) zu übergeben.
Die Funktion, die die Parameter empfängt, muss nicht wissen, dass sie erweitert werden.
Zum Beispiel erwartet xrange von Python 2 nicht explizit *args
aber da es 3 ganze Zahlen als Argumente braucht:
>>> x = xrange(3) # create our *args - an iterable of 3 integers
>>> xrange(*x) # expand here
xrange(0, 2, 2)
Als weiteres Beispiel können wir die dict-Erweiterung in verwenden str.format
:
>>> foo = 'FOO'
>>> bar="BAR"
>>> 'this is foo, {foo} and bar, {bar}'.format(**locals())
'this is foo, FOO and bar, BAR'
Du kannst haben Schlüsselwort nur Argumente nach dem *args
– z.B. hier kwarg2
muss als Schlüsselwortargument angegeben werden – nicht positionell:
def foo(arg, kwarg=None, *args, kwarg2=None, **kwargs):
return arg, kwarg, args, kwarg2, kwargs
Verwendungszweck:
>>> foo(1,2,3,4,5,kwarg2='kwarg2', bar="bar", baz='baz')
(1, 2, (3, 4, 5), 'kwarg2', {'bar': 'bar', 'baz': 'baz'})
Ebenfalls, *
kann allein verwendet werden, um anzugeben, dass nur Schlüsselwortargumente folgen, ohne unbegrenzte Positionsargumente zuzulassen.
def foo(arg, kwarg=None, *, kwarg2=None, **kwargs):
return arg, kwarg, kwarg2, kwargs
Hier, kwarg2
muss wieder ein explizit benanntes Schlüsselwortargument sein:
>>> foo(1,2,kwarg2='kwarg2', foo='foo', bar="bar")
(1, 2, 'kwarg2', {'foo': 'foo', 'bar': 'bar'})
Und wir können nicht länger unbegrenzte Positionsargumente akzeptieren, weil wir sie nicht haben *args*
:
>>> foo(1,2,3,4,5, kwarg2='kwarg2', foo='foo', bar="bar")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: foo() takes from 1 to 2 positional arguments
but 5 positional arguments (and 1 keyword-only argument) were given
Noch einfacher, hier verlangen wir kwarg
namentlich anzugeben, nicht positionell:
def bar(*, kwarg=None):
return kwarg
In diesem Beispiel sehen wir das, wenn wir versuchen zu passen kwarg
positionell erhalten wir einen Fehler:
>>> bar('kwarg')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: bar() takes 0 positional arguments but 1 was given
Wir müssen die ausdrücklich übergeben kwarg
Parameter als Schlüsselwortargument.
>>> bar(kwarg='kwarg')
'kwarg'
*args
(normalerweise “Star-Argumente” genannt) und **kwargs
(Sterne können impliziert werden, indem man “kwargs” sagt, aber mit “double-star kwargs” explizit sein) sind gängige Redewendungen von Python für die Verwendung von *
und **
Notation. Diese spezifischen Variablennamen sind nicht erforderlich (z. B. könnten Sie verwenden *foos
und **bars
), aber eine Abweichung von der Konvention wird Ihre Python-Programmierer wahrscheinlich verärgern.
Wir verwenden diese normalerweise, wenn wir nicht wissen, was unsere Funktion empfangen wird oder wie viele Argumente wir möglicherweise übergeben, und manchmal würde sogar das separate Benennen jeder Variablen sehr chaotisch und überflüssig (aber dies ist ein Fall, in dem dies normalerweise explizit ist besser als implizit).
Beispiel 1
Die folgende Funktion beschreibt, wie sie verwendet werden können, und demonstriert ihr Verhalten. Beachten Sie die benannten b
Das Argument wird vom zweiten Positionsargument vor verbraucht:
def foo(a, b=10, *args, **kwargs):
'''
this function takes required argument a, not required keyword argument b
and any number of unknown positional arguments and keyword arguments after
'''
print('a is a required argument, and its value is {0}'.format(a))
print('b not required, its default value is 10, actual value: {0}'.format(b))
# we can inspect the unknown arguments we were passed:
# - args:
print('args is of type {0} and length {1}'.format(type(args), len(args)))
for arg in args:
print('unknown arg: {0}'.format(arg))
# - kwargs:
print('kwargs is of type {0} and length {1}'.format(type(kwargs),
len(kwargs)))
for kw, arg in kwargs.items():
print('unknown kwarg - kw: {0}, arg: {1}'.format(kw, arg))
# But we don't have to know anything about them
# to pass them to other functions.
print('Args or kwargs can be passed without knowing what they are.')
# max can take two or more positional args: max(a, b, c...)
print('e.g. max(a, b, *args) \n{0}'.format(
max(a, b, *args)))
kweg = 'dict({0})'.format( # named args same as unknown kwargs
', '.join('{k}={v}'.format(k=k, v=v)
for k, v in sorted(kwargs.items())))
print('e.g. dict(**kwargs) (same as {kweg}) returns: \n{0}'.format(
dict(**kwargs), kweg=kweg))
Wir können die Online-Hilfe für die Signatur der Funktion mit überprüfen help(foo)
was uns sagt
foo(a, b=10, *args, **kwargs)
Nennen wir diese Funktion mit foo(1, 2, 3, 4, e=5, f=6, g=7)
was druckt:
a is a required argument, and its value is 1
b not required, its default value is 10, actual value: 2
args is of type <type 'tuple'> and length 2
unknown arg: 3
unknown arg: 4
kwargs is of type <type 'dict'> and length 3
unknown kwarg - kw: e, arg: 5
unknown kwarg - kw: g, arg: 7
unknown kwarg - kw: f, arg: 6
Args or kwargs can be passed without knowing what they are.
e.g. max(a, b, *args)
4
e.g. dict(**kwargs) (same as dict(e=5, f=6, g=7)) returns:
{'e': 5, 'g': 7, 'f': 6}
Beispiel 2
Wir können es auch mit einer anderen Funktion aufrufen, die wir gerade bereitstellen a
:
def bar(a):
b, c, d, e, f = 2, 3, 4, 5, 6
# dumping every local variable into foo as a keyword argument
# by expanding the locals dict:
foo(**locals())
bar(100)
Drucke:
a is a required argument, and its value is 100
b not required, its default value is 10, actual value: 2
args is of type <type 'tuple'> and length 0
kwargs is of type <type 'dict'> and length 4
unknown kwarg - kw: c, arg: 3
unknown kwarg - kw: e, arg: 5
unknown kwarg - kw: d, arg: 4
unknown kwarg - kw: f, arg: 6
Args or kwargs can be passed without knowing what they are.
e.g. max(a, b, *args)
100
e.g. dict(**kwargs) (same as dict(c=3, d=4, e=5, f=6)) returns:
{'c': 3, 'e': 5, 'd': 4, 'f': 6}
Beispiel 3: praktische Anwendung in Dekorateuren
OK, vielleicht sehen wir das Dienstprogramm noch nicht. Stellen Sie sich also vor, Sie haben mehrere Funktionen mit redundantem Code vor und/oder nach dem differenzierenden Code. Die folgenden benannten Funktionen sind nur Pseudocode zu Veranschaulichungszwecken.
def foo(a, b, c, d=0, e=100):
# imagine this is much more code than a simple function call
preprocess()
differentiating_process_foo(a,b,c,d,e)
# imagine this is much more code than a simple function call
postprocess()
def bar(a, b, c=None, d=0, e=100, f=None):
preprocess()
differentiating_process_bar(a,b,c,d,e,f)
postprocess()
def baz(a, b, c, d, e, f):
... and so on
Wir können dies vielleicht anders handhaben, aber wir können die Redundanz sicherlich mit einem Dekorateur extrahieren, und unser Beispiel unten zeigt, wie das geht *args
und **kwargs
kann sehr nützlich sein:
def decorator(function):
'''function to wrap other functions with a pre- and postprocess'''
@functools.wraps(function) # applies module, name, and docstring to wrapper
def wrapper(*args, **kwargs):
# again, imagine this is complicated, but we only write it once!
preprocess()
function(*args, **kwargs)
postprocess()
return wrapper
Und jetzt kann jede verpackte Funktion viel prägnanter geschrieben werden, da wir die Redundanz herausgerechnet haben:
@decorator
def foo(a, b, c, d=0, e=100):
differentiating_process_foo(a,b,c,d,e)
@decorator
def bar(a, b, c=None, d=0, e=100, f=None):
differentiating_process_bar(a,b,c,d,e,f)
@decorator
def baz(a, b, c=None, d=0, e=100, f=None, g=None):
differentiating_process_baz(a,b,c,d,e,f, g)
@decorator
def quux(a, b, c=None, d=0, e=100, f=None, g=None, h=None):
differentiating_process_quux(a,b,c,d,e,f,g,h)
Und indem wir unseren Code ausklammern, der *args
und **kwargs
erlaubt, reduzieren wir Codezeilen, verbessern die Lesbarkeit und Wartbarkeit und haben einzige kanonische Speicherorte für die Logik in unserem Programm. Wenn wir irgendeinen Teil dieser Struktur ändern müssen, haben wir einen Ort, an dem wir jede Änderung vornehmen können.
mrtechmaker
Lassen Sie uns zuerst verstehen, was Positionsargumente und Schlüsselwortargumente sind. Unten ist ein Beispiel für die Funktionsdefinition mit Positionale Argumente.
def test(a,b,c):
print(a)
print(b)
print(c)
test(1,2,3)
#output:
1
2
3
Das ist also eine Funktionsdefinition mit Positionsargumenten. Sie können es auch mit Schlüsselwort/benannten Argumenten aufrufen:
def test(a,b,c):
print(a)
print(b)
print(c)
test(a=1,b=2,c=3)
#output:
1
2
3
Lassen Sie uns nun ein Beispiel für die Funktionsdefinition mit untersuchen Schlüsselwortargumente:
def test(a=0,b=0,c=0):
print(a)
print(b)
print(c)
print('-------------------------')
test(a=1,b=2,c=3)
#output :
1
2
3
-------------------------
Sie können diese Funktion auch mit Positionsargumenten aufrufen:
def test(a=0,b=0,c=0):
print(a)
print(b)
print(c)
print('-------------------------')
test(1,2,3)
# output :
1
2
3
---------------------------------
Wir kennen also jetzt Funktionsdefinitionen mit Positions- und Schlüsselwortargumenten.
Lassen Sie uns nun den ‘*’-Operator und den ‘**’-Operator untersuchen.
Bitte beachten Sie, dass diese Operatoren in 2 Bereichen verwendet werden können:
a) Funktionsaufruf
b) Funktionsdefinition
Die Verwendung des ‘*’-Operators und des ‘**’-Operators in Funktionsaufruf.
Kommen wir gleich zu einem Beispiel und diskutieren es dann.
def sum(a,b): #receive args from function calls as sum(1,2) or sum(a=1,b=2)
print(a+b)
my_tuple = (1,2)
my_list = [1,2]
my_dict = {'a':1,'b':2}
# Let us unpack data structure of list or tuple or dict into arguments with help of '*' operator
sum(*my_tuple) # becomes same as sum(1,2) after unpacking my_tuple with '*'
sum(*my_list) # becomes same as sum(1,2) after unpacking my_list with '*'
sum(**my_dict) # becomes same as sum(a=1,b=2) after unpacking by '**'
# output is 3 in all three calls to sum function.
Also denk daran
wenn der Operator ‘*’ oder ‘**’ in a verwendet wird Funktionsaufruf –
Der Operator ‘*’ entpackt eine Datenstruktur wie eine Liste oder ein Tupel in Argumente, die von der Funktionsdefinition benötigt werden.
Der ‘**’-Operator entpackt ein Wörterbuch in Argumente, die von der Funktionsdefinition benötigt werden.
Lassen Sie uns nun den ‘*’-Operator untersuchen, der in verwendet wird Funktionsdefinition. Beispiel:
def sum(*args): #pack the received positional args into data structure of tuple. after applying '*' - def sum((1,2,3,4))
sum = 0
for a in args:
sum+=a
print(sum)
sum(1,2,3,4) #positional args sent to function sum
#output:
10
In Funktion Definition Der ‘*’-Operator packt die empfangenen Argumente in ein Tupel.
Sehen wir uns nun ein Beispiel für ‘**’ an, das in der Funktionsdefinition verwendet wird:
def sum(**args): #pack keyword args into datastructure of dict after applying '**' - def sum({a:1,b:2,c:3,d:4})
sum=0
for k,v in args.items():
sum+=v
print(sum)
sum(a=1,b=2,c=3,d=4) #positional args sent to function sum
In Funktion Definition Der ‘**’-Operator packt die empfangenen Argumente in ein Dictionary.
Also denk daran:
In einem Funktionsaufruf das ‘*’ auspackt Datenstruktur eines Tupels oder einer Liste in Positions- oder Schlüsselwortargumente, die von der Funktionsdefinition empfangen werden sollen.
In einem Funktionsaufruf das ‘**’ auspackt Datenstruktur des Wörterbuchs in Positions- oder Schlüsselwortargumente, die von der Funktionsdefinition empfangen werden sollen.
In einem Funktionsdefinition das ‘*’ Packungen Positionsargumente in ein Tupel.
In einem Funktionsdefinition das ‘**’ Packungen Schlüsselwortargumente in ein Wörterbuch.
Diese Tabelle ist praktisch für die Verwendung *
und **
in Funktion Konstruktion und Funktion Anruf:
In function construction In function call
=======================================================================
| def f(*args): | def f(a, b):
*args | for arg in args: | return a + b
| print(arg) | args = (1, 2)
| f(1, 2) | f(*args)
----------|--------------------------------|---------------------------
| def f(a, b): | def f(a, b):
**kwargs | return a + b | return a + b
| def g(**kwargs): | kwargs = dict(a=1, b=2)
| return f(**kwargs) | f(**kwargs)
| g(a=1, b=2) |
-----------------------------------------------------------------------
Dies dient wirklich nur dazu, Lorin Hochsteins Antwort zusammenzufassen, aber ich finde es hilfreich.
Verwandte: Verwendungen für die Stern-/Splat-Operatoren waren erweitert in Python3
Bill die Eidechse
*
und **
haben eine besondere Verwendung in der Liste der Funktionsargumente. *
impliziert, dass das Argument eine Liste und ist **
impliziert, dass das Argument ein Wörterbuch ist. Dadurch können Funktionen eine beliebige Anzahl von Argumenten annehmen
siehe auch stackoverflow.com/questions/6967632/…
– Russland muss Putin entfernen
♦
1. März 2018 um 20:53 Uhr
Diese Frage ist ein sehr beliebtes Duplikatziel, wird aber leider oft falsch verwendet. Denken Sie daran, dass diese Frage nach ungefähr fragt Definieren von Funktionen mit varargs (
def func(*args)
). Für eine Frage, was es in Funktion bedeutet Anrufe (func(*[1,2])
) siehe hier. Für eine Fragestellung wie zum Entpacken von Argumentlisten siehe hier. Für eine Frage, was die*
bedeutet hinein Literale ([*[1, 2]]
) siehe hier.– Aran-Fey
22. März 2019 um 20:40 Uhr
@Aran-Fey: Ich denke, ein besseres Ziel für “was bedeutet es in Funktionsaufrufen” ist Was bedeutet der Sternoperator in einem Funktionsaufruf?. Ihr Link befasst sich nicht wirklich mit der Verwendung von
**
und es ist eine viel engere Frage.– ShadowRanger
10. Dezember 2020 um 5:55 Uhr
Diese Frage ist – wie viele sehr alte Fragen – irgendwie rückwärts gerichtet; Normalerweise sollte sich eine Frage darauf beziehen, wie man ein Problem in neuem Code löst, und nicht, wie man bestehenden Code versteht. Wenn Sie für letzteres etwas anderes als Duplikat schließen, ziehen Sie stackoverflow.com/questions/1993727/… in Betracht (obwohl dies nur für
*
und nicht**
).– Karl Knechtel
17. April um 4:51
stackoverflow.com/questions/3394835/use-of-args-and-kwargs wurde ebenfalls als Duplikat davon geschlossen, aber Sie finden es vielleicht besser als dieses.
– Karl Knechtel
21. Juni um 3:31 Uhr