Comme nous le savons tous, il y a la compréhension de la liste, comme
[i for i in [1, 2, 3, 4]]
et il y a la compréhension du dictionnaire, comme
{i:j for i, j in {1: 'a', 2: 'b'}.items()}
mais
(i for i in (1, 2, 3))
se retrouvera dans un générateur, pas une tuple
compréhension. Pourquoi donc?
Je suppose que a tuple
est immuable, mais cela ne semble pas être la réponse.
{i:j for i,j in {1:'a', 2:'b'}}
devrait être{i:j for i,j in {1:'a', 2:'b'}.items()}
Réponses:
Vous pouvez utiliser une expression de générateur:
mais des parenthèses étaient déjà prises pour… les expressions génératrices.
la source
list(i for i in (1,2,3))
. Je pense vraiment que c'est simplement parce qu'il n'y a pas de syntaxe propre (ou du moins personne n'y a pensé)list(i for i in (1, 2, 3))
est une expression de générateur qui génère une liste,set(i for i in (1, 2, 3))
génère un ensemble. Est-ce à dire que la syntaxe de compréhension n'est pas nécessaire? Peut-être pas, mais c'est terriblement pratique. Pour les rares cas où vous avez besoin d'un tuple à la place, l'expression du générateur fera l'affaire, est claire et ne nécessite pas l'invention d'une autre accolade ou d'un support.[thing for thing in things]
construit une liste beaucoup plus rapidement quelist(thing for thing in things)
. Une compréhension de tuple ne serait pas inutile;tuple(thing for thing in things)
a des problèmes de latence ettuple([thing for thing in things])
pourrait avoir des problèmes de mémoire.A list or set or dict comprehension is just syntactic sugar to use a generator expression
? Cela crée de la confusion chez les gens qui considèrent ces derniers comme des moyens équivalents à une fin. Ce n'est pas du sucre techniquement syntaxique car les processus sont en fait différents, même si le produit final est le même.Raymond Hettinger (l'un des développeurs principaux de Python) a dit ceci à propos des tuples dans un tweet récent :
Cela (pour moi) soutient 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, cela devrait être une liste. Bien qu'un tuple soit itérable et semble être simplement une liste immuable, c'est vraiment l'équivalent Python d'une structure C:
devient en Python
la source
operator.itemgetter
dans ce cas.tuple(obj[item] for item in items)
directe. Dans mon cas, j'intégrais cela dans une compréhension de liste pour faire une liste d'enregistrements de tuple. Si je dois le faire à plusieurs reprises dans le code, itemgetter a fière allure. Peut-être que itemgetter serait plus idiomatique de toute façon?Depuis Python 3.5 , vous pouvez également utiliser la
*
syntaxe de décompression de splat pour décompresser une expression de générateur:la source
tuple(list(x for x in range(10)))
( les chemins de code sont identiques , les deux construisant unlist
, la seule différence étant que la dernière étape consiste à créer un àtuple
partir dulist
et à jeter lelist
quand unetuple
sortie est requis). Cela signifie que vous n'évitez pas réellement une paire de temporaires.*(x for x in range(10))
ne fonctionne pas. Je comprendsSyntaxError: can't use starred expression here
. Fonctionne cependanttuple(x for x in range(10))
.Comme l'a
macm
mentionné une autre affiche , le moyen le plus rapide de créer un tuple à partir d'un générateur esttuple([generator])
.Comparaison des performances
Compréhension de la liste:
Tuple de la compréhension de la liste:
Tuple du générateur:
Tuple de déballage:
Ma version de python :
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.
la source
tuple
de listcomp nécessite une utilisation maximale de la mémoire en fonction de la taille combinée du finaltuple
et dulist
.tuple
d'un genexpr, bien que plus lent, signifie que vous ne payez que pour la finaletuple
, pas temporairelist
(le genexpr lui-même occupant une mémoire à peu près fixe). Généralement non significatif, mais il peut être important lorsque les tailles impliquées sont énormes.La compréhension fonctionne en faisant une boucle ou une itération sur des éléments et en les affectant dans un conteneur, un tuple est incapable de recevoir des affectations.
Une fois un tuple créé, il ne peut pas être ajouté, étendu ou attribué à. La seule façon de modifier un Tuple est si l'un de ses objets peut lui-même être affecté (est un conteneur non-tuple). Parce que le tuple ne contient qu'une référence à ce type d'objet.
Aussi - 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:la source
lst = [x for x in ...]; x.append()
?Ma meilleure supposition est qu'ils ont manqué de crochets et ne pensaient pas que ce serait assez utile pour justifier l'ajout d'une syntaxe "laide" ...
la source
{*()}
, bien que laid, il fonctionne comme un ensemble vide littéral!set()
{*[]}
c'est strictement inférieur aux autres options; la chaîne vide et emptytuple
, étant immuables, sont des singletons, donc aucun temporaire n'est nécessaire pour construire le videset
. En revanche, le videlist
n'est pas un singleton, vous devez donc le construire, l'utiliser pour construire leset
, puis le détruire, perdant ainsi tout avantage de performance insignifiant fourni par l'opérateur singe borgne.Les tuples ne peuvent pas être efficacement ajoutés comme une liste.
Ainsi, une compréhension de tuple devrait utiliser une liste en interne, puis la convertir en tuple.
Ce serait la même chose que ce que vous faites maintenant: tuple ([compréhension])
la source
Les parenthèses ne créent pas de tuple. aka one = (two) n'est pas un tuple. Le seul moyen de contourner est soit un = (deux,) ou un = tuple (deux). Une solution est donc:
la source
Je crois que c'est simplement par souci de clarté, nous ne voulons pas encombrer la langue avec trop de symboles différents. De plus, une
tuple
compréhension n'est jamais nécessaire , une liste peut simplement être utilisée à la place avec des différences de vitesse négligeables, contrairement à une compréhension dict par opposition à une compréhension liste.la source
Nous pouvons générer des tuples à partir d'une compréhension de liste. Le suivant ajoute deux nombres séquentiellement dans un tuple et donne une liste des nombres 0-9.
la source