2011-01-01 15 views
17

echar un vistazo al siguiente fragmento de código, que muestra una lista por comprensión ..lista de Python comprensión valor anulando

>>> i = 6 
>>> s = [i * i for i in range(100)] 
>>> print(i) 

Al ejecutar el ejemplo de código en Python 2.6 imprime , pero cuando lo ejecuta en Python 3.x imprime .

¿Cuáles fueron las razones para cambiar el comportamiento y por qué es la salida en Python 3.x?

¡Gracias de antemano!

+2

Wow. Tengo suerte de haberlo encontrado aquí, buscaría el error durante semanas si me tropecé con esto en mi propio código. +1 para pregunta, -1 para Python :( – Kos

+0

Pregunta similar aquí: http://stackoverflow.com/questions/4198906/python-list-comprehension-rebind-names-even-after-scope-of-comprehension-is- esto –

Respuesta

30

El antiguo comportamiento fue un error pero no se pudo solucionar fácilmente ya que algunos códigos se basaban en él.

La variable i dentro de la lista de comprensión debe ser una i diferente de la del nivel superior. Lógicamente, debe tener su propio alcance que no se extienda fuera de la comprensión ya que su valor solo tiene sentido dentro de la comprensión. Pero en Python 2.x debido a un detalle de implementación, el alcance fue más grande de lo necesario, lo que provocó que la variable "se filtrara" al ámbito externo, lo que provocó los resultados confusos que se observan.

Python 3.0 no fue deliberadamente compatible con versiones anteriores, por lo que aprovecharon la oportunidad para corregir este comportamiento indeseable.

En versiones de Python 2.3 y versiones posteriores, una lista de comprensión "filtra" las variables de control de cada una de ellas en el ámbito contenedor. Sin embargo, este comportamiento está en desuso, y confiando en que no funcionará en Python 3,0

Source

7

Sí, hay una razón, y la razón es que no querían que la variable temporal en una lista la comprensión para filtrar en el espacio de nombres externo. Entonces, es un cambio intencional que es el resultado de la comprensión de la lista que ahora es azúcar sintáctica para pasar una expresión del generador a la lista().

Ref: PEP3100.

0

Parece un cambio en el alcance para mí.

He confirmado tu resultado en Python 2.6; de hecho imprime 99, que es el último valor asignado a yo en la lista de comprensión.

4

Mark Byers respondió perfectamente.

simplemente como una nota ..
en Python 2.x, si cambia sus soportes a parens (creando una expresión generador en lugar de una lista por comprensión), se dará cuenta que la variable de control es no filtró .

>>> i = 6 
>>> s = (i for i in range(100)) 
>>> print i 
6 

vs.

>>> i = 6 
>>> s = [i for i in range(100)] 
>>> print i 
99 

(por supuesto, en Python 3, esto es fijo y listas por comprensión ya no fugas variables de control)

+0

Ese es un buen punto. Pero también debe tenerse en cuenta que 's' tampoco contiene una lista, por lo que para obtener el resultado final deseado debe hacer' list (s) '. – Keith

Cuestiones relacionadas