Saltar al contenido
Editor

Comprensiones en Python: listas, diccionarios, conjuntos y más

Intermedio30 min8 ejercicios115 XP

Esta lección es una traducción del original en inglés.Read in EnglishAvisar de un error de traducción

0/8 ejercicios

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.

Bucle normal (4 líneas)
numbers = [1, 2, 3, 4, 5]
squares = []
for n in numbers:
    squares.append(n ** 2)
print(squares)  # [1, 4, 9, 16, 25]
Comprensión de listas (1 línea)
numbers = [1, 2, 3, 4, 5]
squares = [n ** 2 for n in numbers]
print(squares)  # [1, 4, 9, 16, 25]
Comprensiones de listas básicas
# Square each number
numbers = [1, 2, 3, 4, 5]
squares = [n ** 2 for n in numbers]
print(squares)
# Convert names to uppercase
names = ['alice', 'bob', 'charlie']
upper_names = [name.upper() for name in names]
print(upper_names)
# Get the length of each word
words = ['hello', 'world', 'python', 'is', 'fun']
lengths = [len(w) for w in words]
print(lengths)
Salida
[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].

Filtrar con if
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
# Keep only even numbers
evens = [n for n in numbers if n % 2 == 0]
print(evens) # [2, 4, 6, 8, 10]
# Keep only words longer than 3 characters
words = ['hi', 'hello', 'hey', 'world', 'ok', 'python']
long_words = [w for w in words if len(w) > 3]
print(long_words) # ['hello', 'world', 'python']
Salida
[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.

Usar if-else en comprensiones
numbers = [1, 2, 3, 4, 5, 6]
# Label each number as even or odd
labels = ['even' if n % 2 == 0 else 'odd' for n in numbers]
print(labels) # ['odd', 'even', 'odd', 'even', 'odd', 'even']
# Cap scores at 100
raw_scores = [85, 110, 92, 105, 78]
capped = [min(s, 100) for s in raw_scores]
print(capped) # [85, 100, 92, 100, 78]
Salida
['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}.

Comprensiones de diccionarios básicas
# Create a dict of numbers and their squares
squares = {n: n ** 2 for n in range(1, 6)}
print(squares) # {1: 1, 2: 4, 3: 9, 4: 16, 5: 25}
# Create a dict from two lists using zip()
names = ['Alice', 'Bob', 'Charlie']
scores = [95, 87, 72]
grade_book = {name: score for name, score in zip(names, scores)}
print(grade_book) # {'Alice': 95, 'Bob': 87, 'Charlie': 72}
Salida
{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.

Comprensiones de diccionarios con filtro y transformación
prices = {'apple': 1.50, 'banana': 0.75, 'cherry': 3.00, 'date': 5.00}
# Keep only items under $2
affordable = {fruit: price for fruit, price in prices.items() if price < 2}
print(affordable) # {'apple': 1.5, 'banana': 0.75}
# Swap keys and values
flipped = {price: fruit for fruit, price in prices.items()}
print(flipped) # {1.5: 'apple', 0.75: 'banana', 3.0: 'cherry', 5.0: 'date'}
Salida
{'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}.

Comprensiones de conjuntos
# Get unique first letters from a list of names
names = ['Alice', 'Anna', 'Bob', 'Charlie', 'Chloe']
first_letters = {name[0] for name in names}
print(first_letters) # {'A', 'B', 'C'}
# Get unique word lengths
sentence = 'the quick brown fox jumps over the lazy dog'
lengths = {len(word) for word in sentence.split()}
print(sorted(lengths)) # [3, 4, 5]
Salida
{'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.

Comprensión de listas frente a expresión generadora
# List comprehension - builds the entire list in memory
squares_list = [n ** 2 for n in range(5)]
print(squares_list) # [0, 1, 4, 9, 16]
print(type(squares_list)) # <class 'list'>
# Generator expression - generates items on demand
squares_gen = (n ** 2 for n in range(5))
print(squares_gen) # <generator object ...>
print(type(squares_gen)) # <class 'generator'>
# You can loop through a generator
for sq in squares_gen:
print(sq, end=' ')
print()
Salida
[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.

Expresiones generadoras dentro de funciones
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
# Sum of squares using a generator (no extra parentheses needed)
total = sum(n ** 2 for n in numbers)
print(f'Sum of squares: {total}')
# Check if any number is negative
has_negative = any(n < 0 for n in numbers)
print(f'Has negative: {has_negative}')
# Check if all numbers are positive
all_positive = all(n > 0 for n in numbers)
print(f'All positive: {all_positive}')
Salida
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.

Aplanar una lista anidada
# Flatten a list of lists
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
flat = [num for row in matrix for num in row]
print(flat) # [1, 2, 3, 4, 5, 6, 7, 8, 9]
# This is equivalent to:
flat2 = []
for row in matrix:
for num in row:
flat2.append(num)
print(flat2) # [1, 2, 3, 4, 5, 6, 7, 8, 9]
Salida
[1, 2, 3, 4, 5, 6, 7, 8, 9]
[1, 2, 3, 4, 5, 6, 7, 8, 9]
Crear pares de coordenadas
# Create coordinate pairs
coords = [(x, y) for x in range(3) for y in range(3)]
print(coords)
# [(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2), (2, 0), (2, 1), (2, 2)]
Salida
[(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.

Demasiado compleja: difícil de leer
result = [x * 2 if x > 0 else -x for x in data
         if x != 0 and x % 3 == 0]
Bucle claro: fácil de entender
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.

Ejercicio 1: duplica cada número
Escribe el código

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]
numbers = [1, 2, 3, 4, 5]
# Create doubled using a list comprehension
print(doubled)
Ejercicio 2: filtra los números pares
Escribe el código

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]
numbers = [3, 4, 7, 12, 8, 15, 20, 6, 9]
# Create evens using a list comprehension with filtering
print(evens)
Ejercicio 3: predice la salida (if frente a if-else)
Predice la salida

Lee este código con atención y predice qué imprimirá. Fíjate en dónde está el if-else.

Escribe la salida exacta.

nums = [1, 2, 3, 4, 5]
result = ['even' if n % 2 == 0 else 'odd' for n in nums]
print(result)
Ejercicio 4: crea una comprensión de diccionarios
Escribe el código

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}
names = ['Alice', 'Bob', 'Charlie']
# Create name_lengths using a dict comprehension
print(name_lengths)
Ejercicio 5: vocales únicas con una comprensión de conjuntos
Escribe el código

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']
word = 'conversation'
# Find unique vowels using a set comprehension
# Print them sorted
Ejercicio 6: corrige el error de sintaxis en la comprensión
Corrige el error

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']
nums = [3, 8, 2, 9, 1, 7]
result = ['high' for n in nums if n > 5 else 'low']
print(result)
Ejercicio 7: convierte un bucle en una comprensión
Mejora el código

Reescribe el siguiente bucle como una única comprensión de listas. La salida debe quedar exactamente igual.

Salida esperada:

[1, 9, 25, 49, 81]
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9]
result = []
for n in numbers:
if n % 2 != 0:
result.append(n ** 2)
print(result)
Ejercicio 8: aplana una matriz
Escribe el código

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]
45
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
# Flatten using a list comprehension with nested for clauses
# Print the flat list
# Print the sum using a generator expression

Resumen: lo que aprendiste sobre las comprensiones en Python

Este es un repaso de todo lo que ya sabes:

TipoSintaxisCrea
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.

Tutoriales relacionados

¿Te sirvió este tutorial?

Sugerir una mejora