Estaba jugando con listas de comprensión para comprenderlas mejor y me encontré con un resultado inesperado que no puedo explicar. No he encontrado esta pregunta antes, pero si es/es/una pregunta repetida, me disculpo.Python: sintaxis avanzada de comprensión de listas anidadas
Básicamente estaba tratando de escribir un generador que genera generadores. Un generador simple que utiliza lista por comprensión se vería así:
(x for x in range(10) if x%2==0) # generates all even integers in range(10)
Lo que estaba tratando de hacer era escribir un generador que genera dos generadores - el primero de los cuales genera los números pares en la gama (10) y el segundo de los cuales generó los números impares en el rango (10). Para esto, lo hice:
>>> (x for x in range(10) if x%2==i for i in range(2))
<generator object <genexpr> at 0x7f6b90948f00>
>>> for i in g.next(): print i
...
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 1, in <genexpr>
UnboundLocalError: local variable 'i' referenced before assignment
>>> g.next()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
>>> g = (x for x in range(10) if x%2==i for i in range(2))
>>> g
<generator object <genexpr> at 0x7f6b90969730>
>>> g.next()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 1, in <genexpr>
UnboundLocalError: local variable 'i' referenced before assignment
No entiendo por qué 'i' se está haciendo referencia antes de la asignación
pensé que podría haber tenido algo que ver con i in range(2)
, por lo que hice:
>>> g = (x for x in range(10) if x%2==i for i in [0.1])
>>> g
<generator object <genexpr> at 0x7f6b90948f00>
>>> g.next()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 1, in <genexpr>
UnboundLocalError: local variable 'i' referenced before assignment
Esto no tenía sentido para mí, así que pensé que era mejor intentar algo más simple primero. Así que volví a listas y trató:
>>> [x for x in range(10) if x%2==i for i in range(2)]
[1, 1, 3, 3, 5, 5, 7, 7, 9, 9]
que esperaba que ser el mismo que:
>>> l = []
>>> for i in range(2):
... for x in range(10):
... if x%2==i:
... l.append(x)
...
>>> l
[0, 2, 4, 6, 8, 1, 3, 5, 7, 9] # so where is my list comprehension malformed?
Pero cuando lo probé en una corazonada, esto funcionó:
>>> [[x for x in range(10) if x%2==i] for i in range(2)]
[[0, 2, 4, 6, 8], [1, 3, 5, 7, 9]] # so nested lists in nested list comprehension somehow affect the scope of if statements? :S
Así que pensé que podría ser un problema con qué nivel de alcance funciona la instrucción if
. Así que probé esto:
>>> [x for x in range(10) for i in range(2) if x%2==i]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Y ahora estoy completamente confundido. ¿Alguien puede explicar este comportamiento? No entiendo por qué las listas de mi comprensión parecen estar mal formadas, ni entiendo cómo funciona el alcance de las declaraciones if
.
Cualquier ayuda sería grandemente apreciado
Gracias
PD: Mientras corrección de pruebas de la pregunta, me di cuenta de que esto tiene un aspecto un poco como una pregunta tarea - no lo es.
Did '[x para x en el rango (10) si x% 2 == i para i en el rango (2)] '¿trabajo? Estoy obteniendo 'NameError: nombre 'i' no está definido' (Python 2.6.2) –
@ManojGovindan: Obtuve exactamente lo que obtuve (Python 2.6.5) – inspectorG4dget
Relacionado: [nombres de reenvío de la lista de Python incluso después del alcance de la comprensión . ¿Es esto correcto?] (Http://stackoverflow.com/q/4198906) –