Was bedeutet der *
Operator in Python, beispielsweise in Code wie zip(*x)
oder f(**k)
?
- Wie wird es intern im Dolmetscher gehandhabt?
- Beeinträchtigt es überhaupt die Leistung? Ist es schnell oder langsam?
- Wann ist es nützlich und wann nicht?
- Sollte es in einer Funktionsdeklaration oder in einem Aufruf verwendet werden?
*
und**
Betreiber , die nichts mit dieser Syntax zu tun haben.f(**k)
kommt falsch raus wenn du mich fragst :)[*a, b, *c]
oder{**d1, **d2}
) möchten Sie Sternchen in Tupel-, Listen- und Set-Definitionen sowie Doppelsternchen in Diktatdefinition lesen , was für die Verwendung außerhalb von Funktionsaufrufen und Funktionsdefinitionen spezifisch ist . Informationen zum früheren PEP 3132 finden Sie unter Zuweisung mehrerer Entpackungen in Python, wenn Sie die Sequenzlänge nicht kennen .Antworten:
Der einzelne Stern
*
entpackt die Sequenz / Sammlung in Positionsargumente, sodass Sie Folgendes tun können:def sum(a, b): return a + b values = (1, 2) s = sum(*values)
Dadurch wird das Tupel entpackt, sodass es tatsächlich wie folgt ausgeführt wird:
s = sum(1, 2)
Der Doppelstern
**
macht dasselbe, nur unter Verwendung eines Wörterbuchs und damit benannter Argumente:values = { 'a': 1, 'b': 2 } s = sum(**values)
Sie können auch kombinieren:
def sum(a, b, c, d): return a + b + c + d values1 = (1, 2) values2 = { 'c': 10, 'd': 15 } s = sum(*values1, **values2)
wird ausgeführt als:
s = sum(1, 2, c=10, d=15)
Siehe auch Abschnitt 4.7.4 - Entpacken von Argumentlisten der Python-Dokumentation.
Darüber hinaus können Sie zu verwendende Funktionen
*x
und**y
Argumente definieren. Auf diese Weise kann eine Funktion eine beliebige Anzahl von Positions- und / oder benannten Argumenten akzeptieren, die in der Deklaration nicht speziell benannt sind.Beispiel:
def sum(*values): s = 0 for v in values: s = s + v return s s = sum(1, 2, 3, 4, 5)
oder mit
**
:def get_a(**values): return values['a'] s = get_a(a=1, b=2) # returns 1
Auf diese Weise können Sie eine große Anzahl optionaler Parameter angeben, ohne sie deklarieren zu müssen.
Und wieder können Sie kombinieren:
def sum(*values, **options): s = 0 for i in values: s = s + i if "neg" in options: if options["neg"]: s = -s return s s = sum(1, 2, 3, 4, 5) # returns 15 s = sum(1, 2, 3, 4, 5, neg=True) # returns -15 s = sum(1, 2, 3, 4, 5, neg=False) # returns 15
quelle
s = sum((1, 2, 3, 4, 5))
oders = sum([1, 2, 3, 4, 5])
die*values
Option lässt den Aufruf so aussehen, als ob er eine Reihe von Argumenten benötigt, aber sie sind in einer Sammlung für den Funktionscode zusammengefasst.Ein kleiner Punkt: Dies sind keine Operatoren. Operatoren werden in Ausdrücken verwendet, um neue Werte aus vorhandenen Werten zu erstellen (1 + 2 wird beispielsweise zu 3). Die Zeichen * und ** sind hier Teil der Syntax von Funktionsdeklarationen und -aufrufen.
quelle
Ich finde dies besonders nützlich, wenn Sie einen Funktionsaufruf "speichern" möchten.
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 etwas wie add (test [0], test [1]) auszuführen, was hässlich ist. Wenn es eine variable Anzahl von Variablen gibt, kann der Code mit all den if-Anweisungen, die Sie benötigen, 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 Autoobjekte herstellt und zurückgibt. Sie können es so gestalten, dass myFactory.make_car ('rot', 'bmw', '335ix') ein Auto ('rot', 'bmw', '335ix') erstellt und es dann zurückgibt.
def make_car(*args): return Car(*args)
Dies ist auch nützlich, wenn Sie den Konstruktor einer Oberklasse aufrufen möchten.
quelle
Es wird als erweiterte Aufrufsyntax bezeichnet. Aus der Dokumentation :
und:
quelle
apply()
Funktion erreichtIn einem Funktionsaufruf verwandelt der einzelne Stern eine Liste in separate Argumente (z. B.
zip(*x)
ist das gleiche wiezip(x1,x2,x3)
wennx=[x1,x2,x3]
) und der doppelte Stern verwandelt ein Wörterbuch in separate Schlüsselwortargumente (z. B.f(**k)
ist das gleiche wief(x=my_x, y=my_y)
wenn)k = {'x':my_x, 'y':my_y}
.In einer Funktionsdefinition ist es umgekehrt: Der einzelne Stern wandelt eine beliebige Anzahl von Argumenten in eine Liste um, und der Doppelstart verwandelt eine beliebige Anzahl von Schlüsselwortargumenten in ein Wörterbuch. ZB
def foo(*x)
bedeutet "foo nimmt eine beliebige Anzahl von Argumenten und sie sind über die Liste x zugänglich (dh wenn der Benutzer anruftfoo(1,2,3)
,x
wird sein[1,2,3]
)" unddef bar(**k)
bedeutet "bar nimmt eine beliebige Anzahl von Schlüsselwortargumenten und sie sind über das Wörterbuch k zugänglich (dh wenn der Benutzer anruftbar(x=42, y=23)
,k
wird{'x': 42, 'y': 23}
) ".quelle
def foo(*x)
* x gibt ein Tupel, keine Liste.