2.30. Comprensiones¶
Una comprensión construye una nueva lista, conjunto, diccionario o generador a partir de un iterable existente, en una sola expresión. Es un reemplazo del patrón habitual de empezar con un contenedor vacío e ir añadiendo elementos en un bucle.
2.30.1. Comprensiones de listas¶
squares = [x * x for x in range(5)]
print(squares)
Salida:
[0, 1, 4, 9, 16]
El mismo bucle escrito de forma explícita:
squares = []
for x in range(5):
squares.append(x * x)
La forma de comprensión es una sola expresión que construye la lista en el sitio. No hay squares = [] ni .append: el resultado es el valor de la comprensión.
La expresión inicial produce cada elemento; la cláusula for nombra la variable del bucle; una cláusula if opcional filtra elementos.¶
2.30.2. Filtrar con if¶
Una cláusula if opcional conserva solo los elementos que coinciden:
evens = [x for x in range(10) if x % 2 == 0]
print(evens)
Salida:
[0, 2, 4, 6, 8]
El filtro se ejecuta antes que la expresión inicial: x % 2 == 0 se comprueba primero; solo los valores coincidentes llegan a x para la salida.
2.30.3. Comprensiones de diccionarios y conjuntos¶
La misma forma funciona con literales de diccionario y de conjunto.
Una comprensión de diccionario tiene un par key: value antes del for:
squares = {x: x * x for x in range(5)}
print(squares)
Salida:
{0: 0, 1: 1, 2: 4, 3: 9, 4: 16}
Una comprensión de conjunto usa llaves y una sola expresión:
unique_lengths = {len(w) for w in ["a", "bb", "c", "bb"]}
print(unique_lengths)
Salida:
{1, 2}
2.30.4. Expresiones generadoras¶
Los paréntesis redondos producen una expresión generadora en lugar de una lista. Los valores se calculan de uno en uno, bajo demanda:
total = sum(x * x for x in range(1000))
Nunca se construye una lista de un millón de elementos. Los valores fluyen uno a uno hacia sum(), que los suma y descarta cada uno a medida que avanza.
Las expresiones generadoras son la opción correcta cuando se alimentan valores a una función reductora (sum(), max(), any(), all()) o a cualquier otro código que consuma un iterador: ahorran la memoria que habría usado la lista equivalente.
2.30.5. Cuándo no usar una comprensión¶
Las comprensiones son concisas, pero no siempre más claras. Recurre a un bucle for normal cuando:
El cuerpo necesita más de una sentencia (una comprensión admite exactamente una expresión).
El cuerpo tiene efectos secundarios (imprimir, escribir en un archivo): las comprensiones sirven para construir una colección, no para ejecutar acciones.
El filtro o la transformación tiene tantas partes que la comprensión ya no se lee de izquierda a derecha.