Python lista de comprensión doble para

vec = [[1,2,3], [4,5,6], [7,8,9]] print [num for elem in vec for num in elem] >> [1, 2, 3, 4, 5, 6, 7, 8, 9] 

Esto me está engañando.
Entiendo que elem es la lista dentro de la lista de for elem in vic
No entiendo muy bien el uso de num y for num in elem al principio y al final.

¿Cómo interpreta Python esto?
¿Cuál es el orden que se ve?

Vamos a descomponerlo.

Una simple lista de comprensión:

 [x for x in collection] 

Esto es fácil de entender si lo dividimos en partes: [A for B in C]

  • A es el elemento que estará en la lista resultante.
  • B es cada elemento de la colección C
  • C es la propia colección.

De esta manera, se podría escribir:

 [x.lower() for x in words] 

Para convertir todas las palabras de una lista a minúsculas.


Es cuando complicamos esto con otra lista como esta:

 [x for y in collection for x in y] # [A for B in C for D in E] 

Aquí, algo especial sucede. Queremos que nuestra lista final incluya elementos A , y los elementos A se encuentran dentro de B elementos B , por lo que tenemos que decirle a la lista de comprensión que.

  • A es el elemento que estará en la lista resultante.
  • B es cada elemento de la colección C
  • C es la propia colección
  • D es cada elemento de la colección E (en este caso, también A )
  • E es otra colección (en este caso, B )

Esta lógica es similar a la normal para el bucle:

 for y in collection: # for B in C: for x in y: # for D in E: (in this case: for A in B) # receive x # # receive A 

Para ampliar esto, y dar un gran ejemplo + explicación, imagine que hay un tren.

El motor del tren (el frente) siempre estará allí (el resultado de la lista-comprensión)

Luego, hay cualquier número de vagones de tren, cada vagón está en la forma: for x in y

Una lista de comprensión podría verse así:

 [z for b in a for c in b for d in c ... for z in y] 

Lo que sería como tener este bucle for regular:

 for b in a: for c in b: for d in c: ... for z in y: # have z 

En otras palabras, en lugar de ir por una línea y sangrar, en una lista de comprensión simplemente agrega el siguiente bucle al final.

Para volver a la analogía del tren:

EngineCarCarCarTail

¿Qué es la cola? La cola es algo especial en listas de comprensión. No necesitas uno, pero si tienes una cola, la cola es una condición, mira este ejemplo:

 [line for line in file if not line.startswith('#')] 

Esto le daría todas las líneas de un archivo siempre que la línea no comience con un hashtag ( # ), las demás solo se omiten.

El truco para usar la “cola” del tren es que se verifica en Verdadero / Falso al mismo tiempo que tiene su ‘Motor’ o ‘resultado’ final de todos los bucles, el ejemplo anterior en un bucle común se vería así:

 for line in file: if not line.startswith('#'): # have line 

tenga en cuenta: aunque en mi analogía de un tren solo hay una “cola” al final del tren, la condición o “cola” puede ser después de cada “coche” o bucle …

por ejemplo:

 >>> z = [[1,2,3,4],[5,6,7,8],[9,10,11,12]] >>> [x for y in z if sum(y)>10 for x in y if x < 10] [5, 6, 7, 8, 9] 

En bucle for regular:

 >>> for y in z: if sum(y)>10: for x in y: if x < 10: print x 5 6 7 8 9 

De la lista de documentación de comprensión :

Cuando se proporciona una lista de comprensión, consiste en una sola expresión seguida de al menos una for cláusula y cero o más for cláusulas o if las hay. En este caso, los elementos de la nueva lista son aquellos que se producirían considerando cada una de las cláusulas for o if un bloque, anidando de izquierda a derecha y evaluando la expresión para producir un elemento de lista cada vez que se alcanza el bloque más interno .

En otras palabras, simule que los bucles for están nesteds. Leyendo de izquierda a derecha su lista de comprensión puede ser anidada como:

 for elem in vec: for num in elem: num # the *single expression* from the spec 

donde la comprensión de la lista utilizará ese último bloque, más interno, como los valores de la lista resultante.

Su código es igual a:

 temp = [] for elem in vec: for num in elem: temp.append(num)