web-dev-qa-db-fra.com

Pourquoi n'y a-t-il pas de compréhension de Tuple en Python?

Comme nous le savons tous, il existe une compréhension de liste, comme

[i for i in [1, 2, 3, 4]]

et il y a une compréhension du dictionnaire, comme

{i:j for i, j in {1: 'a', 2: 'b'}.items()}

mais

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

aboutira à un générateur, pas à une compréhension Tuple. Pourquoi donc?

À mon avis, une Tuple est immuable, mais cela ne semble pas être la solution.

266
Shady Xu

Vous pouvez utiliser une expression génératrice:

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

mais les parenthèses étaient déjà prises pour… les expressions du générateur.

389
Martijn Pieters

Raymond Hettinger (l'un des Python développeurs principaux) avait ceci à dire à propos des n-uplets dans un Tweet récent :

#python tip: En général, les listes sont pour boucler; tuples pour structs. Les listes sont homogènes; tuples hétérogène.Listes pour longueur variable.

Cela (à mon avis) confirme l'idée que si les éléments d'une séquence sont suffisamment liés pour être générés par un générateur, eh bien, il devrait s'agir d'une liste. Bien qu'un tuple soit itératif et ressemble simplement à une liste immuable, il s'agit en réalité de l'équivalent Python d'une structure C:

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

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

devient en Python

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

Depuis Python 3.5 , vous pouvez également utiliser la syntaxe de décompression * de splat pour décompresser une expression de générateur:

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

La compréhension fonctionne en boucle ou en itérant sur des éléments et en les affectant dans un conteneur, un tuple ne pouvant pas recevoir d’assignations.

Une fois qu'un tuple est créé, il ne peut être ni ajouté, ni étendu, ni attribué. La seule façon de modifier un tuple est si l'un de ses objets peut lui-même être assigné (c'est un conteneur non-tuple). Parce que le Tuple ne contient qu'une référence à ce type d'objet.

De plus, un tuple a son propre constructeur Tuple() que vous pouvez donner à n'importe quel itérateur. Ce qui signifie que pour créer un tuple, vous pouvez faire:

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

Comme l'a mentionné une autre affiche macm, le moyen le plus rapide de créer un tuple à partir d'un générateur est Tuple([generator]).


Comparaison de performance

  • Compréhension de la liste:

    $ python3 -m timeit "a = [i for i in range(1000)]"
    10000 loops, best of 3: 27.4 usec per loop
    
  • Tuple de la compréhension de la liste:

    $ python3 -m timeit "a = Tuple([i for i in range(1000)])"
    10000 loops, best of 3: 30.2 usec per loop
    
  • Tuple du générateur:

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

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

Ma version de python:

$ python3 --version
Python 3.6.3

Vous devez donc toujours créer un tuple à partir d’une liste de compréhension, sauf si les performances ne sont pas un problème.

17
Tom

Ma meilleure hypothèse est qu'ils sont à court de crochets et ne pensent pas qu'il serait assez utile de justifier l'ajout d'une syntaxe "laide" ...

13
mgilson

Les tuples ne peuvent pas être ajoutés efficacement comme une liste.

Ainsi, une compréhension de Tuple devrait utiliser une liste en interne puis être convertie en Tuple.

Ce serait la même chose que ce que vous faites maintenant: Tuple ([compréhension])

6
macm

Les parenthèses ne créent pas un tuple. aka un = (deux) n'est pas un tuple. Le seul moyen de contourner est un = (deux) ou un = Tuple (deux). Donc, une solution est:

Tuple(i for i in myothertupleorlistordict) 
2
ilias iliadis