Comprensiones en Python: listas, diccionarios, conjuntos y más
Esta lección es una traducción del original en inglés.Read in EnglishAvisar de un error de traducción
Imagina que tienes una lista de 100 números y quieres una lista nueva solo con los pares, cada uno multiplicado por dos. Con un bucle normal, eso ocupa cuatro líneas. Con una comprensión de Python (en inglés, comprehension), basta una.
Las comprensiones son una de las características más queridas de Python. Te permiten crear listas, diccionarios y conjuntos nuevos describiendo qué quieres, en lugar de escribir paso a paso cómo construirlos.
En esta lección aprenderás los cuatro tipos de comprensiones (de listas, de diccionarios, de conjuntos y expresiones generadoras), además de los filtros, las condiciones y una pregunta importante: cuándo NO usarlas.
Comprensión de listas: el patrón más común
Una comprensión de listas (list comprehension) crea una lista nueva aplicando una expresión a cada elemento de una secuencia existente. La sintaxis es: [expression for item in iterable].
Piensa en ella como un bucle for compacto que construye una lista. En vez de crear una lista vacía y añadir elementos dentro de un bucle, describes el resultado en una sola línea.
numbers = [1, 2, 3, 4, 5]
squares = []
for n in numbers:
squares.append(n ** 2)
print(squares) # [1, 4, 9, 16, 25]numbers = [1, 2, 3, 4, 5]
squares = [n ** 2 for n in numbers]
print(squares) # [1, 4, 9, 16, 25][1, 4, 9, 16, 25] ['ALICE', 'BOB', 'CHARLIE'] [5, 5, 6, 2, 3]
Cómo añadir condiciones a las comprensiones
Puedes añadir una cláusula if para filtrar elementos. Solo los elementos que cumplen la condición entran en la lista nueva. La sintaxis es: [expression for item in iterable if condition].
[2, 4, 6, 8, 10] ['hello', 'world', 'python']
También puedes usar una expresión if-else para transformar los elementos de forma distinta según una condición. Pero fíjate en el cambio de sintaxis: el if-else va antes del for, no después.
['odd', 'even', 'odd', 'even', 'odd', 'even'] [85, 100, 92, 100, 78]
Comprensión de diccionarios
Las comprensiones de diccionarios funcionan igual que las de listas, pero crean diccionarios. Usa llaves y una expresión key: value. La sintaxis es: {key: value for item in iterable}.
{1: 1, 2: 4, 3: 9, 4: 16, 5: 25}
{'Alice': 95, 'Bob': 87, 'Charlie': 72}También puedes filtrar con if, igual que en las comprensiones de listas. Es muy útil para quedarte con una parte de un diccionario.
{'apple': 1.5, 'banana': 0.75}
{1.5: 'apple', 0.75: 'banana', 3.0: 'cherry', 5.0: 'date'}Comprensión de conjuntos
Las comprensiones de conjuntos crean conjuntos: colecciones sin duplicados. Usan llaves, igual que las de diccionarios, pero sin los dos puntos. La sintaxis es: {expression for item in iterable}.
{'B', 'C', 'A'}
[3, 4, 5]La diferencia clave con las comprensiones de listas es que los conjuntos eliminan los duplicados automáticamente. Aunque "Alice" y "Anna" empiezan con "A", el conjunto solo contiene una "A".
Expresiones generadoras: comprensiones que ahorran memoria
Una expresión generadora se parece a una comprensión de listas, pero usa paréntesis en lugar de corchetes. La gran diferencia: no crea todos los elementos a la vez. Los genera uno a uno, a medida que se piden.
Esto importa cuando trabajas con datos muy grandes. Una comprensión de listas de un millón de elementos crea en memoria una lista de un millón de elementos. Una expresión generadora casi no usa memoria: calcula cada elemento solo cuando se lo pides.
[0, 1, 4, 9, 16] <class 'list'> <generator object <genexpr> at 0x4fc5898> <class 'generator'> 0 1 4 9 16
Las expresiones generadoras se usan mucho dentro de funciones como sum(), max() y min(). Puedes omitir los paréntesis extra cuando el generador es el único argumento.
Sum of squares: 385 Has negative: False All positive: True
Comprensiones anidadas
Puedes poner una cláusula for dentro de otra para manejar bucles anidados. Primero va el bucle exterior y luego el interior. Esto sirve para aplanar listas o crear cuadrículas.
[1, 2, 3, 4, 5, 6, 7, 8, 9] [1, 2, 3, 4, 5, 6, 7, 8, 9]
[(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2), (2, 0), (2, 1), (2, 2)]
Cuándo NO usar comprensiones
Las comprensiones son potentes, pero no siempre son la mejor opción. Si una comprensión cuesta leerla, es mejor un bucle normal. Un código claro siempre vale más que uno ingenioso.
Evita las comprensiones cuando: la lógica es compleja y tiene varias condiciones, necesitas efectos secundarios como imprimir dentro del bucle, o la comprensión ocupa más de unos 80 caracteres de ancho.
result = [x * 2 if x > 0 else -x for x in data
if x != 0 and x % 3 == 0]result = []
for x in data:
if x != 0 and x % 3 == 0:
if x > 0:
result.append(x * 2)
else:
result.append(-x)Además, nunca uses una comprensión solo por sus efectos secundarios. Si vas a llamar a print() o a modificar una variable externa, usa un bucle normal. Una comprensión siempre debe servir para construir una colección nueva.
Ejercicios de práctica
¡Hora de practicar! Estos ejercicios cubren los cuatro tipos de comprensiones, desde lo básico hasta patrones más exigentes.
Usa una comprensión de listas para crear una lista llamada doubled que contenga cada número de la lista dada multiplicado por 2.
Salida esperada:
[2, 4, 6, 8, 10]Usa una comprensión de listas con una cláusula if para crear una lista llamada evens que contenga solo los números pares de la lista dada.
Salida esperada:
[4, 12, 8, 20, 6]Lee este código con atención y predice qué imprimirá. Fíjate en dónde está el if-else.
Escribe la salida exacta.
Usa una comprensión de diccionarios para crear un diccionario llamado name_lengths que asocie cada nombre con su longitud.
Salida esperada:
{'Alice': 5, 'Bob': 3, 'Charlie': 7}Usa una comprensión de conjuntos para encontrar todas las vocales distintas de la palabra dada. Guarda el resultado en una variable llamada vowels_found y luego imprímelo ordenado como lista.
Salida esperada:
['a', 'e', 'i', 'o']Este código intenta crear una lista en la que los números mayores que 5 se etiquetan como 'high' y los demás como 'low'. Pero la sintaxis está mal y el programa falla. Corrígelo.
Salida esperada:
['low', 'high', 'low', 'high', 'low', 'high']Reescribe el siguiente bucle como una única comprensión de listas. La salida debe quedar exactamente igual.
Salida esperada:
[1, 9, 25, 49, 81]Usa una comprensión de listas con dos cláusulas for para aplanar la matriz dada (una lista de listas) en una sola lista plana. Luego imprime la suma de todos los elementos con una expresión generadora dentro de sum().
Salida esperada:
[1, 2, 3, 4, 5, 6, 7, 8, 9]
45Resumen: lo que aprendiste sobre las comprensiones en Python
Este es un repaso de todo lo que ya sabes:
| Tipo | Sintaxis | Crea |
|---|---|---|
| Comprensión de listas | [expr for x in items] | Una lista |
| Lista filtrada | [expr for x in items if cond] | Una lista filtrada |
| Lista transformada | [a if cond else b for x in items] | Una lista transformada |
| Comprensión de diccionarios | {k: v for x in items} | Un diccionario |
| Comprensión de conjuntos | {expr for x in items} | Un conjunto (sin duplicados) |
| Expresión generadora | (expr for x in items) | Un generador perezoso |
| Comprensión anidada | [expr for a in X for b in a] | Una lista aplanada |
Las comprensiones son una de las señas de identidad de Python. Hacen tu código más corto, más legible (si las usas bien) y, a menudo, más rápido que los bucles equivalentes.
¿Qué sigue?
Ahora que sabes crear y transformar colecciones con soltura, puedes pasar a las [tuplas en Python](/python/python-tuples): secuencias inmutables, perfectas para datos fijos como coordenadas, registros y valores de retorno de funciones.
Verás por qué la inmutabilidad es útil, cómo funcionan el empaquetado y el desempaquetado de tuplas, y cuándo conviene elegir una tupla en lugar de una lista.