La gramática es: transformación, bucle, filtro; izquierda, centro y derecha. Todos los ejemplos de abajo son esa misma frase reordenada.
🎙️ Publicado y grabado:
nums = [1, 2, 3, 4, 5]
[n * n for n in nums] # transforma → [1,4,9,16,25]
[n for n in nums if n % 2 == 0] # filtra → [2,4]
[n*n for n in nums if n > 2] # ambas cosas → [9,16,25]
["even" if n%2==0 else "odd" for n in nums] # if-else → a la IZQUIERDALa posición de if-else que hace tropezar a todo el mundo: el if que filtra va a la derecha y descarta elementos; el if-else que elige va a la izquierda, conserva todos los elementos y decide su valor. Confundirlos es el error de sintaxis más común en una comprensión.
# limpia una lista de cadenas
[s.strip().lower() for s in raw if s.strip()]
# extrae un campo de una lista de diccionarios (¡respuestas de API!)
[u["email"] for u in users if u["active"]]
# convierte en números los valores de una fila CSV
[float(x) for x in line.split(",")]
# nombres de archivo que coinciden con un patrón
[f for f in os.listdir(".") if f.endswith(".csv")]
{w: len(w) for w in words} # diccionario: {"hi": 2, "hello": 5}
{u["id"]: u for u in users} # indexa una lista por id: uso cotidiano
{n % 3 for n in nums} # conjunto: solo valores únicos
{v: k for k, v in d.items()} # invierte un diccionario
matrix = [[1, 2], [3, 4], [5]]
[x for row in matrix for x in row] # → [1,2,3,4,5]
# lee los for de izquierda a derecha, igual que los bucles anidados.
# este es también el límite: un nivel. si hay más, escribe un bucle.
[print(x) for x in items]), eso es un bucle disfrazado que además reserva una lista inútil de valores None. Y cuando una comprensión necesita dos if o condiciones anidadas, tu yo del futuro agradecerá un bucle. Lo ingenioso cabe en una línea; lo mantenible se entiende de un vistazo.sum(), max() o any()? Quita los corchetes: sum(n*n for n in nums). Eso es una expresión generadora: misma sintaxis, sin lista intermedia, y se nota cuando los datos son grandes.