91 votes

liste compréhension sans [], Python

Voici la chose, rejoignez une liste:

 >>> ''.join([ str(_) for _ in xrange(10) ])
'0123456789'
 

join doit prendre un itératif.

Apparemment, join l » argument est [ str(_) for _ in xrange(10) ] , et une liste-compréhension.

Regarde ça:

 >>>''.join( str(_) for _ in xrange(10) )
'0123456789'
 

Maintenant, join l » argument est juste str(_) for _ in xrange(10) , pas [] , mais le résultat est le même.

Pourquoi? Est-ce que str(_) for _ in xrange(10) produit également une liste ou une liste pouvant être itérative?

142voto

Raymond Hettinger Points 50330

Les autres répondants ont été corriger dans la réponse que vous aviez découvert un générateur d'expression (qui a une notation similaire à interprétations de la liste, mais sans les environs crochets).

En général, genexps (comme on l'appelle affectueusement) sont de mémoire, plus efficace et plus rapide que les interprétations de la liste.

CEPENDANT, c'est le cas de l' ''.join(), une compréhension de liste est à la fois plus rapide et plus efficace en terme de mémoire. La raison en est que de jointure doit faire deux passes sur les données, si elle a effectivement besoin d'une véritable liste. Si vous lui en donner une, il peut commencer à travailler immédiatement. Si vous lui donnez un genexp au lieu de cela, il ne peut pas commencer à travailler jusqu'à ce qu'il construit une nouvelle liste dans la mémoire par l'exécution de l'genexp à l'épuisement:

~ $ python -m timeit '"".join(str(n) for n in xrange(1000))'
1000 loops, best of 3: 335 usec per loop
~ $ python -m timeit '"".join([str(n) for n in xrange(1000)])'
1000 loops, best of 3: 288 usec per loop

Le même résultat s'applique lorsque l'on compare les itertools.imap rapport à la carte:

~ $ python -m timeit -s'from itertools import imap' '"".join(imap(str, xrange(1000)))'
1000 loops, best of 3: 220 usec per loop
~ $ python -m timeit '"".join(map(str, xrange(1000)))'
1000 loops, best of 3: 212 usec per loop

73voto

NPE Points 169956
 >>>''.join( str(_) for _ in xrange(10) )
 

Ceci s'appelle une expression génératrice et est expliqué dans PEP 289 .

La principale différence entre les expressions du générateur et les compréhensions de liste est que les premiers ne créent pas la liste en mémoire.

Notez qu'il existe une troisième façon d'écrire l'expression:

 ''.join(map(str, xrange(10)))
 

5voto

kindall Points 60645

Votre deuxième exemple utilise un générateur d'expression plutôt qu'une compréhension de liste. La différence est que, avec la compréhension de liste, une liste est complètement construit et transmis à l' .join(). Avec le générateur d'expression, les éléments sont générés un par un et consommés en .join(). Ce dernier utilise moins de mémoire et est généralement plus rapide.

Comme il arrive, la liste constructeur sera heureux de consommer tout itératif, y compris un générateur d'expression. Donc:

[str(n) for n in xrange(10)]

est juste "sucre syntaxique" pour:

list(str(n) for n in xrange(10))

En d'autres termes, une compréhension de liste est juste un générateur d'expression qui est transformée en une liste.

5voto

monkut Points 14549

Comme mentionné, c'est une expression génératrice .

De la documentation:

Les parenthèses peuvent être omises lors d'appels avec un seul argument. Voir la section Appels pour plus de détails.

4voto

sblom Points 15074

Si c'est dans les parenthèses, mais pas entre parenthèses, il est techniquement un générateur d'expression. Générateur d'expressions ont été d'abord introduit en Python 2.4.

http://wiki.python.org/moin/Generators

La partie après le rejoindre, ( str(_) for _ in xrange(10) ) est, par elle-même, un générateur d'expression. Vous pourriez faire quelque chose comme:

mylist = (str(_) for _ in xrange(10))
''.join(mylist)

et ça veut dire exactement la même chose que vous avez écrit dans le deuxième cas ci-dessus.

Les générateurs de certaines des propriétés très intéressantes, et non la moindre, est qu'ils ne finissent pas l'allocation de l'ensemble de la liste lorsque vous n'en avez pas besoin. Au lieu de cela, une fonction comme join "pompes" les éléments du générateur d'expression, un à un, de son travail sur les petites parties intermédiaires.

Dans vos exemples, la liste et le générateur n'est probablement pas effectuer terriblement différemment, mais en général, je préfère utiliser le générateur d'expressions (et même générateur de fonctions) dès que je peux, surtout parce que c'est extrêmement rare pour un générateur à être plus lent que d'une liste complète matérialisation.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X