while una lista for elementos ejemplos cambiar bucle anidado python python-3.x loops for-loop list-comprehension

lista - ¿Por qué puedes recorrer una tupla implícita en un bucle for, pero no una comprensión en Python?



if en python (3)

¿Hay alguna razón por la que hacer un bucle a través de una tupla implícita en un bucle for esté bien, pero cuando lo haces en una comprensión, aparece un error de sintaxis?

Por ejemplo:

for i in ''a'',''b'',''c'': print(i) ''a'' ''b'' ''c''

Pero en una comprensión:

>>> [i for i in ''a'',''b'',''c''] File "<stdin>", line 1 [i for i in ''a'',''b'',''c''] ^ SyntaxError: invalid syntax

¿Hay alguna razón para esto? No estaba seguro de la terminología correcta, por lo que mis búsquedas no resultaron útiles.

Actualizar:

Según los comentarios, esta sintaxis es válida para Python 2.x, pero no para Python 3.x.


Creo que el problema está aquí: en este último caso, no es tan obvio qué objetos estás iterando:

>>> [i for i in (''a'',''b'',''c'')] [''a'', ''b'', ''c'']

¿Dónde hay un borde entre elementos? ¿Es una matriz de 3 elementos: generador y 2 enteros? Me gusta esto:

>>> [(i for i in ''a''),''b'',''c''] [<generator object <genexpr> at 0x10cefeeb8>, ''b'', ''c'']

Porque no tiene tanta ambigüedad, por lo que no necesita paréntesis.


Debido a que el for i in el primer código es una construcción sintáctica diferente que el for i in en el segundo código.

El primer caso es una declaración for , que tiene la gramática :

for_stmt ::= "for" target_list "in" expression_list ":" suite ["else" ":" suite]

''a'', ''b'', ''c'' es definitivamente una expression_list , por lo que funciona.

Sin embargo, en el segundo caso, la línea for corchetes internos obliga a interpretar el código como una lista de comprensión, y en Python 3, la lista de comprensión debe tener la sintaxis :

comprehension ::= expression comp_for comp_for ::= "for" target_list "in" or_test [comp_iter] comp_iter ::= comp_for | comp_if comp_if ::= "if" expression_nocond [comp_iter]

Tenga en cuenta que la parte posterior a la entrada debe ser or_test , pero las expresiones delimitadas por comas crean listas de expresiones , y una lista de expresiones no puede ser or_test --- o, dicho de otra manera, or tiene una prioridad más alta que la coma. Python piensa así que la comprensión termina en coma, de modo que los tres elementos de la lista son:

i for i in ''a'' ''b'' ''c''

que (a menos que ponga la i for i in ''a'' entre paréntesis) es obviamente inválido.

En cuanto a por qué esto funciona en Python 2 ... todavía estoy buscando.


Esto cambió en Python3, principalmente para que las comprensiones de listas sean más consistentes con las expresiones generadoras.

Con los bucles for y la comprensión de listas, no hay ambigüedad cuando se usa una tupla sin paréntesis, porque la primera siempre termina con dos puntos y la última con un corchete de cierre o una palabra clave for/if .

Sin embargo, parte del diseño de las expresiones generadoras requiere que se puedan usar "desnudos" como argumentos de función:

>>> list(i for i in range(3)) [0, 1, 2]

lo que crea cierta ambigüedad para las tuplas sin paréntesis, porque cualquier coma puede introducir un nuevo argumento:

>>> list(i for i in 0, 1, 2) File "<stdin>", line 1 SyntaxError: Generator expression must be parenthesized if not sole argument

Por lo tanto, las tuplas siempre deben estar entre paréntesis en las expresiones del generador, y la misma restricción ahora también se aplica a las comprensiones de la lista para preservar la consistencia.

PD:

Guido van Rossum escribió un artículo que explica todos los detalles sobre este tema en su blog History of Python: