76 votes

Pourquoi les compréhensions de liste écrivent-elles dans la variable de boucle, mais pas les générateurs?

Si je fais quelque chose avec les interprétations de la liste, il écrit à une variable locale:

i = 0
test = any([i == 2 for i in xrange(10)])
print i

Ce imprime "9". Cependant, si j'utilise un générateur, il n'a pas d'écrire dans une variable locale:

i = 0
test = any(i == 2 for i in xrange(10))
print i

Cette affiche "0".

Est-il une bonne raison pour cette différence? Est-ce une décision de conception, ou seulement de façon aléatoire un sous-produit de la façon dont les générateurs et les interprétations de la liste sont mises en œuvre? Personnellement, il semble qu'il serait mieux pour moi si les interprétations de la liste n'a pas écrit pour les variables locales.

74voto

poke Points 64398

Python créateur, Guido van Rossum, mentionne lorsqu'il écrit à propos de générateur d'expressions qui ont tous été construits en Python 3: (c'est moi qui souligne)

Nous avons également fait un autre changement en Python 3, afin d'améliorer l'équivalence entre les interprétations de la liste et le générateur d'expressions. En Python 2, la compréhension de liste de "fuite" de la variable de contrôle de boucle dans les environs du champ d'application:

x = 'before'
a = [x for x in 1, 2, 3]
print x # this prints '3', not 'before'

C'était un artefact de l'origine de la mise en œuvre des interprétations de la liste; il a été l'un de Python "dirty little secrets" pendant des années. Il a commencé comme un acte intentionnel de compromis à faire des interprétations de la liste aveuglément rapides, et tandis qu'il n'était pas un piège classique pour les débutants, c'est très certainement piqué gens de temps en temps. Pour le générateur d'expressions que nous ne pouvions pas faire cela. Générateur d'expressions sont mises en œuvre à l'aide de générateurs, dont l'exécution exige une exécution séparée cadre. Ainsi, le générateur d'expressions (surtout si elles itérer sur une courte séquence) étaient moins efficaces que les interprétations de la liste.

Toutefois, en Python 3, nous avons décidé de fixer le "sale petit secret" des interprétations de la liste en utilisant la même stratégie de mise en œuvre que pour le générateur d'expressions. Ainsi, en Python 3, l'exemple ci-dessus (après modification de l'utilisation de l'impression(x) :-) apparaîtra à l'impression "d'avant", prouvant que le " x "dans la compréhension de liste temporairement ombre, mais ne remplace pas le" x " dans les environs du champ d'application.

Donc en Python 3, vous ne verrez pas cela se reproduire.

Il est intéressant de noter, dict interprétations en Python 2 ne pas le faire; c'est surtout parce que dict interprétations ont été réalignés à partir de Python 3 et en tant que tel déjà eu ce correctif.

Il y a d'autres questions qui traitent de ce sujet, mais je suis sûr que vous avez déjà vu ces lorsque vous avez effectué une recherche pour le sujet, non? ;)

16voto

Simeon Visser Points 30697

Comme PEP 289 (Générateur d'Expressions) explique:

La variable de boucle (si c'est une variable simple ou un n-uplet de simples variables) n'est pas exposé à l'air fonction. Cela facilite la mise en œuvre et rend des cas d'utilisation typique plus fiable.

Il semble avoir été fait pour la mise en œuvre des raisons.

Personnellement, il semble qu'il serait mieux pour moi si les interprétations de la liste n'a pas écrit pour les variables locales.

PEP 289 précise ceci:

Interprétations de la liste aussi "fuite" de leur variable de boucle dans les environs du champ d'application. Cela permettra également de modifier en Python 3.0, de sorte que la définition sémantique d'une compréhension de liste en Python 3.0 sera équivalent à la liste().

En d'autres termes, le comportement que vous décrivez diffère en effet en Python 2, mais il a été résolu dans Python 3.

9voto

Personnellement, il me semblerait préférable que les compréhensions de liste n'écrivent pas dans des variables locales.

Vous avez raison. Ceci est corrigé dans Python 3.x. Le comportement est inchangé dans la version 2.x afin qu'il n'ait pas d'impact sur le code existant qui (ab) utilise ce trou.

4voto

Eevee Points 18333

Parce que parce que.

Non, vraiment, c'est tout. Quirk de la mise en œuvre. Et sans doute un bug, puisqu'il est corrigé dans Python 3.

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