Was bedeuten ** (Doppelstern/Stern) und * (Stern/Stern) in einem Funktionsaufruf?
Lesezeit: 6 Minuten
Psihodelie
Im Code wie zip(*x) oder f(**k)was machen die * Und ** bzw. bedeuten? Wie implementiert Python dieses Verhalten und was sind die Auswirkungen auf die Leistung?
Siehe auch: Tupel in Argumente erweitern. Bitte verwenden Sie diese, um Fragen zu schließen, bei denen OP verwendet werden muss * auf einen Streit und weiß nicht, dass es existiert.
Siehe Was bewirkt ** (Doppelsternchen/Sternchen) und * (Sternchen/Sternchen) für Parameter? für die ergänzende Frage zu den Parametern.
Nachtrag: stackoverflow.com/questions/1141504/…
– Wds
27. Mai 2010 um 15:10 Uhr
Ich denke, dies sollte als “* Funktionsaufrufsyntax” formuliert werden. Sie sind keine Operatoren, obwohl es dort verwirrend wird Ist A * Und ** Operatoren, die nichts mit dieser Syntax zu tun haben.
– Ian Bicking
28. Mai 2010 um 2:45 Uhr
@Ian Bicking: Sie haben volles Recht, * und ** in der Argumentliste sind reine Syntax (Token).
– P. Ortiz
31. Oktober 2015 um 21:13 Uhr
Hinweis: Für PEP 448: Zusätzliche Verallgemeinerungen beim Entpacken bestimmte Sachen (zB [*a, b, *c] oder {**d1, **d2}), sollten Sie Sternchen in Tupel-, Listen- und Set-Definitionen lesen, doppeltes Sternchen in Diktdefinition, was für die Verwendung spezifisch ist außen von Funktionsaufrufen und Funktionsdefinitionen. Für früher PEP 3132siehe Multiple Unpacking Assignment in Python, wenn Sie die Sequenzlänge nicht kennen.
– ShadowRanger
22. März 2019 um 20:14 Uhr
Lasse V. Karlsen
Ein einzelner Stern * entpackt eine Sequenz oder Sammlung in Positionsargumente. Angenommen, wir haben
def add(a, b):
return a + b
values = (1, 2)
Verwendung der * Auspackoperator können wir schreiben s = add(*values)was dem Schreiben entspricht s = add(1, 2).
Der Doppelstern ** macht dasselbe für ein Wörterbuch und liefert Werte für benannte Argumente:
values = { 'a': 1, 'b': 2 }
s = add(**values) # equivalent to add(a=1, b=2)
Beide Operatoren können für denselben Funktionsaufruf verwendet werden. Zum Beispiel gegeben:
def sum(a, b, c, d):
return a + b + c + d
values1 = (1, 2)
values2 = { 'c': 10, 'd': 15 }
Dann s = add(*values1, **values2) ist äquivalent zu s = sum(1, 2, c=10, d=15).
Ähnlich, * Und ** kann für Parameter verwendet werden. Verwenden * ermöglicht einer Funktion, eine beliebige Anzahl von Positionsargumenten zu akzeptieren, die in einem einzigen Parameter gesammelt werden:
def add(*values):
s = 0
for v in values:
s = s + v
return s
Wenn die Funktion nun wie aufgerufen wird s = add(1, 2, 3, 4, 5), values wird das Tupel sein (1, 2, 3, 4, 5) (was natürlich das Ergebnis liefert 15).
Ebenso ein mit gekennzeichneter Parameter ** erhält ein dict:
Dies ermöglicht die Angabe einer großen Anzahl optionaler Parameter, ohne sie deklarieren zu müssen.
Auch hier kann beides kombiniert werden:
def add(*values, **options):
s = 0
for i in values:
s = s + i
if "neg" in options:
if options["neg"]:
s = -s
return s
s = add(1, 2, 3, 4, 5) # returns 15
s = add(1, 2, 3, 4, 5, neg=True) # returns -15
s = add(1, 2, 3, 4, 5, neg=False) # returns 15
Warum würden Sie das brauchen, könnte die Funktion nicht einfach über die bereitgestellte Liste iterieren, ohne dass sie erweitert wird?
– Martin Beckett
27. Mai 2010 um 14:27 Uhr
Sicher, aber dann müsste man es nennen: s = sum((1, 2, 3, 4, 5)) oder s = sum([1, 2, 3, 4, 5])Die *values -Option lässt den Aufruf so aussehen, als würde er eine Reihe von Argumenten benötigen, aber sie werden in eine Sammlung für den Funktionscode gepackt.
– Lasse V. Karlsen
27. Mai 2010 um 14:29 Uhr
Hier ist der eigentliche Vorteil: Sie können Funktionen schreiben, die sonst nicht möglich wären, wenn Sie eine variable Anzahl von Argumenten benötigen. Zum Beispiel ist die C-Funktion printf, die 1+n Argumente hat, als Übung für jeden Programmieranfänger schwierig zu schreiben. In Python kann ein Anfänger def printf(string_template, *args) schreiben und weitermachen.
– IceArdor
20. November 2013 um 7:38 Uhr
Was passiert, wenn Sie (aus Versehen vielleicht :p) ein Wörterbuch mit nur einem * statt zwei entpacken? Es scheint etwas zu tun, es scheint, als würde ein Tupel herauskommen, aber es ist nicht so offensichtlich, was es ist. (edit: ok, ich denke, die Antwort ist, dass es nur die Schlüssel entpackt, die Werte werden verworfen)
– Ben Farmer
15. September 2017 um 7:47 Uhr
Das letzte Beispiel impliziert, dass * und ** nicht nur entpacken, sondern auch packen! Sehen Sie sich diese hervorragende Seite an codegame.com/playgrounds/500/…
– HCChen
17. Februar 2019 um 4:06 Uhr
sepp2k
In einem Funktionsaufruf verwandelt der einzelne Stern eine Liste in separate Argumente (z zip(*x) ist das gleiche wie zip(x1, x2, x3) gegeben x=[x1,x2,x3]) und der Doppelstern verwandelt ein Wörterbuch in separate Schlüsselwortargumente (z f(**k) ist das gleiche wie f(x=my_x, y=my_y) gegeben k = {'x':my_x, 'y':my_y}.
Bei einer Funktionsdefinition ist es umgekehrt: Der einzelne Stern verwandelt eine beliebige Anzahl von Argumenten in eine Liste, und der Doppelstart verwandelt eine beliebige Anzahl von Schlüsselwortargumenten in ein Wörterbuch. Z.B def foo(*x) bedeutet “foo nimmt eine beliebige Anzahl von Argumenten und sie werden durch zugänglich sein x (dh wenn der Benutzer anruft foo(1,2,3), x wird sein (1, 2, 3))” Und def bar(**k) bedeutet “bar nimmt eine beliebige Anzahl von Schlüsselwortargumenten und sie werden durch zugänglich sein k (dh wenn der Benutzer anruft bar(x=42, y=23), k wird sein {'x': 42, 'y': 23})”.
Donald Bergmann
Ich finde das besonders nützlich, um Argumente für einen Funktionsaufruf zu speichern.
Angenommen, ich habe einige Komponententests für eine Funktion „add“:
def add(a, b):
return a + b
tests = { (1,4):5, (0, 0):0, (-1, 3):3 }
for test, result in tests.items():
print('test: adding', test, '==', result, '---', add(*test) == result)
Es gibt keine andere Möglichkeit, add aufzurufen, als manuell so etwas wie add(test[0], test[1]), was hässlich ist. Auch wenn es eine variable Anzahl von Variablen gibt, könnte der Code mit all den if-Anweisungen, die Sie benötigen würden, ziemlich hässlich werden.
Ein weiterer nützlicher Ort ist das Definieren von Factory-Objekten (Objekte, die Objekte für Sie erstellen). Angenommen, Sie haben eine Klasse Factory, die Car-Objekte erstellt und zurückgibt. Du könntest es so machen myFactory.make_car('red', 'bmw', '335ix') schafft Car('red', 'bmw', '335ix')gibt es dann zurück.
def make_car(*args):
return Car(*args)
Dies ist auch nützlich, wenn Sie den Konstruktor einer Oberklasse aufrufen möchten.
Ich mag deine Beispiele. Aber ich denke -1 + 3 == 2.
– eksortso
27. Mai 2010 um 20:32 Uhr
Ich habe absichtlich etwas eingefügt, das fehlschlagen würde 🙂
– Donald Bergmann
28. Mai 2010 um 18:15 Uhr
Markus Byers
Sie wird als erweiterte Aufrufsyntax bezeichnet. Von dem Dokumentation:
Wenn die Syntax *Ausdruck im Funktionsaufruf erscheint, muss Ausdruck zu einer Sequenz ausgewertet werden. Elemente aus dieser Sequenz werden behandelt, als wären sie zusätzliche Positionsargumente; Wenn Positionsargumente x1,…, xN vorhanden sind und Ausdruck zu einer Folge y1, …, yM ausgewertet wird, entspricht dies einem Aufruf mit M+N Positionsargumenten x1, …, xN, y1, . .., yM.
Und:
Wenn die Syntax **Ausdruck im Funktionsaufruf erscheint, muss Ausdruck zu einer Zuordnung ausgewertet werden, deren Inhalt als zusätzliche Schlüsselwortargumente behandelt werden. Wenn ein Schlüsselwort sowohl im Ausdruck als auch als explizites Schlüsselwortargument erscheint, wird eine TypeError-Ausnahme ausgelöst.
14490800cookie-checkWas bedeuten ** (Doppelstern/Stern) und * (Stern/Stern) in einem Funktionsaufruf?yes
Nachtrag: stackoverflow.com/questions/1141504/…
– Wds
27. Mai 2010 um 15:10 Uhr
Ich denke, dies sollte als “* Funktionsaufrufsyntax” formuliert werden. Sie sind keine Operatoren, obwohl es dort verwirrend wird Ist A
*
Und**
Operatoren, die nichts mit dieser Syntax zu tun haben.– Ian Bicking
28. Mai 2010 um 2:45 Uhr
@Ian Bicking: Sie haben volles Recht, * und ** in der Argumentliste sind reine Syntax (Token).
– P. Ortiz
31. Oktober 2015 um 21:13 Uhr
Hinweis: Für PEP 448: Zusätzliche Verallgemeinerungen beim Entpacken bestimmte Sachen (zB
[*a, b, *c]
oder{**d1, **d2}
), sollten Sie Sternchen in Tupel-, Listen- und Set-Definitionen lesen, doppeltes Sternchen in Diktdefinition, was für die Verwendung spezifisch ist außen von Funktionsaufrufen und Funktionsdefinitionen. Für früher PEP 3132siehe Multiple Unpacking Assignment in Python, wenn Sie die Sequenzlänge nicht kennen.– ShadowRanger
22. März 2019 um 20:14 Uhr