it-swarm.com.de

Warum gibt es in Python kein Tupel-Verständnis?

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 ein Tuple unveränderlich ist, aber dies scheint nicht die Antwort zu sein.

266
Shady Xu

Sie können einen Generatorausdruck verwenden:

Tuple(i for i in (1, 2, 3))

aber für ... Generatorausdrücke wurden bereits Klammern gesetzt.

389
Martijn Pieters

Raymond Hettinger (einer der Kernentwickler von Python) hatte Folgendes über Tupel in einem aktuellen Tweet zu sagen:

#python-Tipp: Im Allgemeinen sind Listen für das Schleifen gedacht. Tupel für Strukturen. Listen sind homogen; Tupel heterogen. Listen für variable Länge.

Dies unterstützt (für mich) die Idee, dass, wenn die Elemente in einer Sequenz so miteinander verknüpft sind, dass sie von einem Generator generiert werden können, es sich um eine Liste handeln sollte. Obwohl ein Tupel iterabel ist und wie eine unveränderliche Liste aussieht, ist es tatsächlich das Python - Äquivalent einer C-Struktur:

struct {
    int a;
    char b;
    float c;
} foo;

struct foo x = { 3, 'g', 5.9 };

wird in Python

x = (3, 'g', 5.9)
63
chepner

Seit Python 3.5 können Sie splat * Auch zum Entpacken eines Generatorausdrucks verwenden:

*(x for x in range(10)),
46
czheo

Das Verständnis funktioniert durch Schleifen oder Iterieren von Elementen und Zuweisen zu einem Container. 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 (es handelt sich um einen 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. Was bedeutet, dass Sie zum Erstellen eines Tupels Folgendes tun können:

Tuple(i for i in (1,2,3))
22
Inbar Rose

Wie in einem anderen Poster macm erwähnt, ist der schnellste Weg, ein Tupel aus einem Generator zu erstellen, Tuple([generator]).


Leistungsvergleich

  • Listenverständnis:

    $ python3 -m timeit "a = [i for i in range(1000)]"
    10000 loops, best of 3: 27.4 usec per loop
    
  • Tupel vom Listenverständnis:

    $ python3 -m timeit "a = Tuple([i for i in range(1000)])"
    10000 loops, best of 3: 30.2 usec per loop
    
  • Tupel vom Generator:

    $ python3 -m timeit "a = Tuple(i for i in range(1000))"
    10000 loops, best of 3: 50.4 usec per loop
    
  • Tupel vom Auspacken:

    $ python3 -m timeit "a = *(i for i in range(1000)),"
    10000 loops, best of 3: 52.7 usec per loop
    

Meine Version von Python:

$ python3 --version
Python 3.6.3

Sie sollten daher immer ein Tupel aus einem Listenverständnis erstellen, es sei denn, die Leistung spielt keine Rolle.

17
Tom

Ich vermute, dass ihnen die Klammern ausgegangen sind und ich dachte nicht, dass es nützlich genug wäre, um eine "hässliche" Syntax zu rechtfertigen ...

13
mgilson

Tupel können nicht effizient wie eine Liste angehängt werden.

Ein Tupel-Verstä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])

6
macm

Klammern erzeugen kein Tupel. aka one = (two) ist kein Tupel. Der einzige Ausweg ist entweder eins = (zwei,) oder eins = Tupel (zwei). Eine Lösung ist also:

Tuple(i for i in myothertupleorlistordict) 
2
ilias iliadis