Sternchen im Funktionsaufruf


111

Ich verwende itertools.chain, um eine Liste von Listen auf diese Weise zu "reduzieren":

uniqueCrossTabs = list(itertools.chain(*uniqueCrossTabs))

Wie ist das anders als zu sagen:

uniqueCrossTabs = list(itertools.chain(uniqueCrossTabs))

8
Weitere Informationen finden Sie unter Entpacken von Argumentlisten in den Python-Dokumenten.
Kai

8
Sie sollten auch den **Operator überprüfen - er funktioniert genauso wie *mit Schlüsselwortargumenten.
Sean Vieira

Antworten:


181

* ist der "splat" -Operator: Er nimmt eine Liste als Eingabe und erweitert sie im Funktionsaufruf zu tatsächlichen Positionsargumenten.

Also wenn uniqueCrossTabsja [ [ 1, 2 ], [ 3, 4 ] ], dannitertools.chain(*uniqueCrossTabs) ist das dasselbe wie zu sagenitertools.chain([ 1, 2 ], [ 3, 4 ])

Dies unterscheidet sich offensichtlich von der gerechten Übergabe uniqueCrossTabs. In Ihrem Fall haben Sie eine Liste von Listen, die Sie reduzieren möchten. Wasitertools.chain() geben einen Iterator über die Verkettung aller Positionsargumente zurück, die Sie an ihn übergeben, wobei jedes Positionsargument für sich iterierbar ist.

Mit anderen Worten, Sie möchten jede Liste uniqueCrossTabsals Argument übergeben chain(), das sie miteinander verkettet, aber Sie haben die Listen nicht in separaten Variablen, also verwenden Sie die* Operator, um die Liste der Listen in mehrere Listenargumente zu erweitern.

Wie Jochen Ritzel in den Kommentaren ausgeführt hat, chain.from_iterable()ist es für diese Operation besser geeignet, da zunächst eine einzige Iterable von Iterablen angenommen wird. Ihr Code wird dann einfach:

uniqueCrossTabs = list(itertools.chain.from_iterable(uniqueCrossTabs))

9
@larsmans: Ich denke, der Begriff ist in der Ruby-Welt populärer, aber er scheint auch für Python akzeptabel zu sein. Ich mag ihn, weil es Spaß macht zu sagen ;-)
Cameron

1
@larsmans: Interessant! Ich dachte immer, es beziehe sich auf das Auspacken der Liste in eine Argumentliste, nicht auf das eigentliche Zeichen.
Cameron

1
Vielleicht sind Strings nicht das beste Beispiel, weil nicht jeder Strings als iterable ansieht. Übrigens: Anstatt zu chain(*it)schreiben chain.from_iterable(it).
Jochen Ritzel

@Jochen: Du hast absolut Recht, ich werde es ändern, um stattdessen Zahlen zu verwenden. Außerdem wusste ich nicht einmal, dass es from_iterableexistiert! Ich werde es in Kürze in meine Antwort aufnehmen
Cameron

1
@Ramy: *dient nur zum Auflösen der Liste in Positionsargumente für eine Funktion (also ja, sehr spezifisch). Sie können tun for l in uniqueCrossTabs:, um über sie zu iterieren. Leider ist es *bei der Arbeit schwer zu erkennen , da es nur funktioniert, wenn Sie eine Liste an eine Funktion übergeben (anstatt die Liste als ersten Parameter zu übergeben, *wird jedes Element in der Liste nacheinander als separater Parameter übergeben , als ob sie in der Parameterliste durch Kommas getrennt abgetippt worden wären)
Cameron

72

Es teilt die Sequenz in separate Argumente für den Funktionsaufruf auf.

>>> def foo(a, b=None, c=None):
...   print a, b, c
... 
>>> foo([1, 2, 3])
[1, 2, 3] None None
>>> foo(*[1, 2, 3])
1 2 3
>>> def bar(*a):
...   print a
... 
>>> bar([1, 2, 3])
([1, 2, 3],)
>>> bar(*[1, 2, 3])
(1, 2, 3)

sukzessive Erklärung mit Beispielen. +1!
AruniRC

28

Nur eine alternative Art, das Konzept zu erklären / zu verwenden.

import random

def arbitrary():
    return [x for x in range(1, random.randint(3,10))]

a, b, *rest = arbitrary()

# a = 1
# b = 2
# rest = [3,4,5]

3
Dies ist wichtig und wird an keiner anderen Stelle erwähnt
Gershom

1
Diese Antwort bezieht sich nicht speziell auf die Frage, sondern ist eine wichtige Anwendung des Sternchens (daher halte ich es unter dem eher "nebligen" Titel für angemessen). Aus dem gleichen Grund gibt es eine weitere wichtige Anwendung in Funktionsdefinitionen: Weitere Informationen finden def func(a, b, *args):Sie in dieser Antwort .
ASL
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.