Wie wir alle wissen, gibt es Listenverständnis wie
[i for i in [1, 2, 3, 4]]
und es gibt Wörterbuchverständnis, wie
{i:j for i, j in {1: 'a', 2: 'b'}.items()}
aber
(i for i in (1, 2, 3))
wird in einem Generator enden, nicht in einem tuple
Verständnis. Warum ist das so?
Ich vermute, dass a tuple
unveränderlich ist, aber dies scheint nicht die Antwort zu sein.
{i:j for i,j in {1:'a', 2:'b'}}
sollte sein{i:j for i,j in {1:'a', 2:'b'}.items()}
Antworten:
Sie können einen Generatorausdruck verwenden:
Für… Generatorausdrücke wurden jedoch bereits Klammern gesetzt.
quelle
list(i for i in (1,2,3))
. Ich denke wirklich, es liegt einfach daran, dass es keine saubere Syntax dafür gibt (oder zumindest niemand daran gedacht hat)list(i for i in (1, 2, 3))
ist ein Generatorausdruck, der eine Liste undset(i for i in (1, 2, 3))
eine Menge ausgibt. Bedeutet das, dass die Verständnissyntax nicht benötigt wird? Vielleicht nicht, aber es ist schrecklich praktisch. In den seltenen Fällen, in denen Sie stattdessen ein Tupel benötigen, reicht der Generatorausdruck aus, ist klar und erfordert nicht die Erfindung einer anderen Klammer oder Klammer.[thing for thing in things]
erstellt eine Liste viel schneller alslist(thing for thing in things)
. Ein Tupelverständnis wäre nicht nutzlos;tuple(thing for thing in things)
hat Latenzprobleme undtuple([thing for thing in things])
könnte Speicherprobleme haben.A list or set or dict comprehension is just syntactic sugar to use a generator expression
? Es verursacht Verwirrung, wenn Menschen diese als gleichwertige Mittel zum Zweck betrachten. Es ist technisch gesehen kein syntaktischer Zucker, da die Prozesse tatsächlich unterschiedlich sind, selbst wenn das Endprodukt das gleiche ist.Raymond Hettinger (einer der Python-Kernentwickler) hatte kürzlich in einem Tweet Folgendes über Tupel zu sagen :
Dies (für mich) unterstützt die Idee, dass es eine Liste sein sollte, wenn die Elemente in einer Sequenz so verwandt sind, dass sie von einem Generator generiert werden können. Obwohl ein Tupel iterierbar ist und einfach wie eine unveränderliche Liste erscheint, ist es wirklich das Python-Äquivalent einer C-Struktur:
wird in Python
quelle
operator.itemgetter
in diesem Fall verwenden.tuple(obj[item] for item in items)
. In meinem Fall habe ich dies in ein Listenverständnis eingebettet, um eine Liste von Tupeldatensätzen zu erstellen. Wenn ich dies im gesamten Code wiederholt tun muss, sieht itemgetter großartig aus. Vielleicht wäre Itemgetter so oder so idiomatischer?Seit Python 3.5 können Sie auch die
*
Syntax zum Entpacken von Splat verwenden , um einen Generatorausdruck zu entpacken:quelle
tuple(list(x for x in range(10)))
( die Codepfade sind identisch , wobei beide einlist
erstellen, mit dem einzigen Unterschied, dass der letzte Schritt darin besteht, eintuple
aus dem zu erstellenlist
und daslist
Wanntuple
wegzulassen, wenn eine Ausgabe erfolgt ist erforderlich). Bedeutet, dass Sie ein Paar von Provisorien nicht wirklich vermeiden.*(x for x in range(10))
funktioniert nicht. Ich versteheSyntaxError: can't use starred expression here
. Funktioniert jedochtuple(x for x in range(10))
.Wie in einem anderen Poster
macm
erwähnt, ist der schnellste Weg, ein Tupel aus einem Generator zu erstellen, dertuple([generator])
.Leistungsvergleich
Listenverständnis:
Tupel aus Listenverständnis:
Tupel vom Generator:
Tupel vom Auspacken:
Meine Version von Python :
Sie sollten daher immer ein Tupel aus einem Listenverständnis erstellen, es sei denn, die Leistung spielt keine Rolle.
quelle
tuple
listcomp ist eine maximale Speichernutzung erforderlich, die auf der kombinierten Größe von finaltuple
und basiertlist
.tuple
Wenn ein Genexpr langsamer ist, bedeutet dies, dass Sie nur für das Finale bezahlentuple
, nicht für das Temporärelist
(der Genexpr selbst belegt ungefähr einen festen Speicher). Normalerweise nicht sinnvoll, aber es kann wichtig sein, wenn die beteiligten Größen sehr groß sind.Zum Verständnis werden Elemente wiederholt oder iteriert und einem Container zugewiesen. Ein Tupel kann keine Zuweisungen empfangen.
Sobald ein Tupel erstellt wurde, kann es nicht mehr angehängt, erweitert oder zugewiesen werden. Die einzige Möglichkeit, ein Tupel zu ändern, besteht darin, dass eines seiner Objekte selbst zugewiesen werden kann (ein Nicht-Tupel-Container). Weil das Tupel nur einen Verweis auf diese Art von Objekt enthält.
Außerdem hat ein Tupel einen eigenen Konstruktor,
tuple()
den Sie jedem Iterator geben können. Um ein Tupel zu erstellen, können Sie Folgendes tun:quelle
lst = [x for x in ...]; x.append()
?Ich gehe davon aus, dass ihnen die Klammern ausgegangen sind und sie nicht der Meinung waren, dass dies nützlich genug wäre, um das Hinzufügen einer "hässlichen" Syntax zu rechtfertigen ...
quelle
{*()}
, obwohl hässlich, als leeres Set-Literal funktioniert!set()
:){*[]}
den anderen Optionen strikt unterlegen ist. Die leere Zeichenfolge und die leere Zeichenfolgetuple
sind unveränderlich und Singletons. Daher wird keine temporäre Zeichenfolge benötigt, um die leere Zeichenfolge zu erstellenset
. Im Gegensatz dazu ist das Leerzeichenlist
kein Singleton. Sie müssen es also tatsächlich konstruieren, zum Erstellen verwendenset
und dann zerstören, wobei Sie den trivialen Leistungsvorteil verlieren, den der einäugige Affenoperator bietet.Tupel können nicht effizient wie eine Liste angehängt werden.
Ein Tupelverständnis müsste also eine Liste intern verwenden und dann in ein Tupel konvertieren.
Das wäre das gleiche wie das, was Sie jetzt tun: Tupel ([Verständnis])
quelle
Klammern erzeugen kein Tupel. aka one = (two) ist kein Tupel. Der einzige Weg ist entweder eins = (zwei,) oder eins = Tupel (zwei). Eine Lösung ist also:
quelle
Ich glaube, es ist nur der Klarheit halber, wir wollen die Sprache nicht mit zu vielen verschiedenen Symbolen überladen. Auch ein
tuple
Verständnis ist niemals notwendig , eine Liste kann stattdessen nur mit vernachlässigbaren Geschwindigkeitsunterschieden verwendet werden, im Gegensatz zu einem Diktatverständnis im Gegensatz zu einem Listenverständnis.quelle
Wir können Tupel aus einem Listenverständnis generieren. Der folgende fügt zwei Zahlen nacheinander zu einem Tupel hinzu und gibt eine Liste mit den Zahlen 0-9 an.
quelle