Comprensión de Listas
Aprende la sintaxis de comprensión de listas en Python, filtrado, bucles anidados, comprensiones de diccionarios y conjuntos, con ejemplos ejecutables.
Comprensión de Listas en Python
La comprensión de listas es una forma concisa de construir una nueva lista aplicando una expresión a cada elemento de un iterable — filtrando elementos de forma opcional con una condición — todo en una única línea legible. Esta página cubre la sintaxis completa, patrones comunes, comprensiones de diccionarios y conjuntos, y orientación sobre cuándo un bucle for simple es la mejor opción.
Sintaxis
La forma general de una comprensión de listas es:
new_list = [expression for item in iterable if condition]| Parte | Función |
|---|---|
expression | Valor colocado en la nueva lista para cada item |
item | Variable del bucle, toma cada valor de iterable en orden |
iterable | Cualquier secuencia o iterable: lista, tupla, string, range, etc. |
if condition | Filtro opcional — solo se incluyen los elementos donde la condición es True |
La parte if condition es opcional. Cuando se omite, cada elemento del iterable produce una entrada en la nueva lista.
Ejemplo Básico: Elevar Números al Cuadrado
El bucle for equivalente requiere tres líneas; la comprensión de listas hace lo mismo en una:
Filtrado con una Condición
Añade una cláusula if después del iterable para conservar solo los elementos que satisfacen una condición:
Puedes combinar cualquier predicado. Por ejemplo, conservar palabras que tienen más de cuatro caracteres:
words = ['hi', 'hello', 'world', 'python', 'ai']
long_words = [w for w in words if len(w) > 4]
print(long_words) # ['hello', 'world', 'python']if/else en la Expresión (Ternario)
Cuando necesitas transformar cada elemento pero aplicar lógica diferente según una condición, coloca el if/else dentro de la parte de la expresión (antes de for), no después del iterable:
numbers = range(1, 6)
labels = ['even' if x % 2 == 0 else 'odd' for x in numbers]
print(labels) # ['odd', 'even', 'odd', 'even', 'odd']Nota la diferencia:
[expr for x in it if cond]— filtro: omite los elementos dondecondesFalse[a if cond else b for x in it]— transformación: cada elemento produce un valor, elegido porcond
Trabajando con Strings
La comprensión de listas funciona con cualquier iterable, incluidos strings y listas de strings:
words = ['hello', 'world', 'python']
upper_words = [w.upper() for w in words]
print(upper_words) # ['HELLO', 'WORLD', 'PYTHON']Extrae caracteres individuales que cumplen una condición:
vowels = [ch for ch in 'programming' if ch in 'aeiou']
print(vowels) # ['o', 'a', 'i']Bucles Anidados
La comprensión de listas admite múltiples cláusulas for, equivalentes a bucles anidados. El for más a la izquierda es el bucle externo:
Un caso de uso común para la comprensión de listas anidada es aplanar una lista 2-D (matriz) en una lista 1-D:
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
flat = [n for row in matrix for n in row]
print(flat) # [1, 2, 3, 4, 5, 6, 7, 8, 9]Consejo de lectura: expande mentalmente las comprensiones anidadas como bucles for anidados en el mismo orden de izquierda a derecha.
Comprensión de Diccionarios
La misma idea se aplica a los diccionarios usando {} con una expresión clave: valor:
keys = ['a', 'b', 'c']
values = [1, 2, 3]
mapping = {k: v for k, v in zip(keys, values)}
print(mapping) # {'a': 1, 'b': 2, 'c': 3}Intercambia claves y valores en un diccionario existente:
original = {'name': 'Alice', 'city': 'Paris'}
inverted = {v: k for k, v in original.items()}
print(inverted) # {'Alice': 'name', 'Paris': 'city'}Comprensión de Conjuntos
Usa {} con una expresión simple (sin dos puntos) para construir un conjunto, que elimina duplicados automáticamente:
numbers = [1, 2, 2, 3, 3, 3, 4]
unique_squares = {x ** 2 for x in numbers}
print(unique_squares) # {1, 4, 9, 16}El resultado no tiene orden garantizado (los conjuntos no tienen un orden definido), así que no confíes en la secuencia impresa.
Rendimiento
Las comprensiones de listas son generalmente más rápidas que los bucles for equivalentes que llaman a .append() porque el intérprete puede optimizar el bucle interno en C. Para medir el tiempo de tu propio código, usa el módulo timeit:
import timeit
loop_time = timeit.timeit(
'result = []\nfor x in range(1000):\n result.append(x**2)',
number=10000
)
comp_time = timeit.timeit(
'[x**2 for x in range(1000)]',
number=10000
)
print(f'Loop: {loop_time:.3f}s')
print(f'Comprehension: {comp_time:.3f}s')
# Comprehension is typically 20-40% fasterLa ventaja de rendimiento disminuye o desaparece cuando la expresión en sí es lenta (I/O de red, cómputo intensivo). Perfila el código antes de optimizar.
Cuándo Usar un Bucle for Simple en su Lugar
La comprensión de listas no siempre es la herramienta adecuada:
| Situación | Preferir |
|---|---|
| Una sola transformación o filtro | Comprensión de listas |
| Múltiples efectos secundarios por iteración (registro, mutación de estado) | Bucle for |
| Lógica compleja que requiere varias instrucciones | Bucle for |
| Comprensiones profundamente anidadas (más de dos niveles) | Bucle for — la legibilidad gana |
| El resultado nunca se almacena (solo necesitas iterar) | Expresión generadora ((x for x in ...)) |
La señal más clara para volver a un bucle for es cuando te encuentras esforzándote por entender qué hace la comprensión.
Aspectos a Tener en Cuenta
La fuga de variables no ocurre en Python 3. La variable del bucle en una comprensión tiene alcance dentro de la propia comprensión:
x = 'original'
result = [x * 2 for x in range(3)]
print(x) # 'original' — not overwritten by the comprehension's xEvita las comprensiones profundamente anidadas. Más de dos cláusulas for en una sola comprensión perjudica la legibilidad con poco beneficio. Divídelas en listas intermedias con nombre o bucles for.
Las expresiones generadoras ahorran memoria. Si solo necesitas iterar sobre el resultado una vez (por ejemplo, pasarlo a sum() o max()), reemplaza [] con () para obtener un generador que produce elementos uno a uno:
total = sum(x ** 2 for x in range(1, 1001))
print(total) # 333833500