▷ List comprehensions en Python — La guía completa con ejemplos 2026

List comprehensions en Python — La guía completa con ejemplos

Si llevas un tiempo programando Python, seguro que has visto código tipo [x*2 for x in numeros] y te has quedado mirando la pantalla pensando: “¿qué brujería es esto?”. Tranquilo, le pasa a todo el mundo la primera vez.

Las list comprehensions son una de las cosas más Python de Python. Una vez las dominas, ves bucles con append y te da picor leer el código. Esta entrada es la guía definitiva: desde lo básico hasta los trucos que casi nadie cuenta — incluido cuándo no usarlas (sí, hay casos donde son peor que un bucle normal).

Qué es una list comprehension

Una list comprehension es una forma compacta de crear una lista a partir de otra cosa iterable (una lista, una tupla, un range, un string…) en una sola línea.

La forma larga, que ya conoces, es esta:

numeros = [1, 2, 3, 4, 5]

dobles = []
for n in numeros:
    dobles.append(n * 2)

print(dobles)  # [2, 4, 6, 8, 10]

Cuatro líneas para algo tan simple. La forma compacta:

numeros = [1, 2, 3, 4, 5]
dobles = [n * 2 for n in numeros]
print(dobles)  # [2, 4, 6, 8, 10]

Una línea. Mismo resultado. Más rápido (Python las optimiza internamente). Y, una vez te acostumbras, mucho más legible.

La sintaxis, despiezada

La estructura es siempre la misma:

[ expresion   for  variable  in  iterable ]
     ↑                                     ↑
  qué guardas                       de dónde lo saco

Si lo lees de izquierda a derecha:

“Crea una lista con n*2 para cada n que esté en numeros.”

Pista mental: lee la línea como una frase en inglés (“multiply n by 2 for each n in numeros“) y la entiendes a la primera.

Filtros: añadir un if

Aquí empieza la magia. Puedes añadir un filtro al final:

numeros = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

pares = [n for n in numeros if n % 2 == 0]
print(pares)  # [2, 4, 6, 8, 10]

Lectura: “guarda n para cada n en numeros si n es par”.

Equivalente largo (para que veas lo que ahorras):

pares = []
for n in numeros:
    if n % 2 == 0:
        pares.append(n)

Otro ejemplo más útil — quedarse con palabras largas:

palabras = ["sol", "elefante", "luz", "extraordinario", "casa"]
largas = [p for p in palabras if len(p) > 4]
print(largas)  # ['elefante', 'extraordinario']

📥 Llévate el cheatsheet de Python (gratis)

PDF de 6 páginas con lo esencial: tipos, condicionales, bucles, estructuras de datos, funciones y los errores que más vas a cometer. Para tener al lado mientras programas.

Sin spam. Te apuntas a la lista, descargas el cheatsheet y recibes contenido de Python cada semana.

Transformaciones: cambiar lo que guardas

La parte de la izquierda no tiene por qué ser la variable tal cual — puede ser cualquier expresión:

nombres = ["ana", "PEDRO", "Luis", "MARÍA"]

# Capitalizar todos
capitalizados = [n.capitalize() for n in nombres]
print(capitalizados)  # ['Ana', 'Pedro', 'Luis', 'María']

# Longitud de cada nombre
longitudes = [len(n) for n in nombres]
print(longitudes)  # [3, 5, 4, 5]

# Tuplas (nombre, longitud)
con_longitud = [(n.capitalize(), len(n)) for n in nombres]
print(con_longitud)  # [('Ana', 3), ('Pedro', 5), ('Luis', 4), ('María', 5)]

Combinando transformación + filtro

Lo típico que harás el 80% del tiempo:

numeros = range(1, 11)  # 1 a 10

# Cuadrados de los pares
cuadrados_pares = [n ** 2 for n in numeros if n % 2 == 0]
print(cuadrados_pares)  # [4, 16, 36, 64, 100]

Y un caso más realista — limpiar y filtrar datos de un formulario:

respuestas = ["  ", "Madrid", "barcelona  ", "", "  VALENCIA"]

# Quitar espacios, capitalizar y dejar solo las que tengan algo
ciudades = [r.strip().capitalize() for r in respuestas if r.strip()]
print(ciudades)  # ['Madrid', 'Barcelona', 'Valencia']

Tres operaciones (strip, capitalize, filtro) en una línea. Ahí es donde brillan.

El if/else en la expresión (cuidado, distinto al filtro)

Mucha gente se lía con esto al principio. Hay dos formas de meter un if en una list comprehension:

numeros = [1, 2, 3, 4, 5, 6]

# Forma 1 — FILTRO (al final): mantiene solo los que cumplen
filtrados = [n for n in numeros if n % 2 == 0]
print(filtrados)  # [2, 4, 6]

# Forma 2 — TERNARIO (en la expresión): siempre incluye, pero transforma
etiquetados = ["par" if n % 2 == 0 else "impar" for n in numeros]
print(etiquetados)  # ['impar', 'par', 'impar', 'par', 'impar', 'par']

Diferencia clave:

  • Filtro if al final: decide si incluir el elemento. La lista resultante tiene igual o menos elementos.
  • Ternario if/else al principio: decide qué guardas para cada elemento. La lista resultante tiene el mismo número de elementos.

⚠️ Atención: si quieres if/else en la expresión, necesitas el else. Si solo quieres filtrar, va al final sin else. Mezclar las dos sintaxis es el error más común al empezar.

Comprehensions anidadas: dos for

Cuando trabajas con listas de listas (matrices, datos tabulares…) puedes anidar:

# Aplanar una matriz 2D a una lista 1D
matriz = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
plana = [n for fila in matriz for n in fila]
print(plana)  # [1, 2, 3, 4, 5, 6, 7, 8, 9]

Lectura: “para cada fila en matriz, para cada n en fila, guarda n“. El orden es el mismo que tendría el bucle anidado:

plana = []
for fila in matriz:        # bucle externo
    for n in fila:         # bucle interno
        plana.append(n)

Otro caso típico — pares de combinaciones:

# Producto cartesiano de dos listas
colores = ["rojo", "azul"]
tallas = ["S", "M", "L"]
combinaciones = [(c, t) for c in colores for t in tallas]
print(combinaciones)
# [('rojo', 'S'), ('rojo', 'M'), ('rojo', 'L'),
#  ('azul', 'S'), ('azul', 'M'), ('azul', 'L')]

💡 Tip-friki: si usas mucho producto cartesiano, mira itertools.product. Hace lo mismo más explícito y compone mejor con otros iterables: list(product(colores, tallas)).

Lista de listas: anidación a la inversa

Si lo que quieres es construir una matriz, la expresión es una lista entera:

# Tabla de multiplicar 3x3
tabla = [[i * j for j in range(1, 4)] for i in range(1, 4)]
print(tabla)
# [[1, 2, 3],
#  [2, 4, 6],
#  [3, 6, 9]]

Lectura: “por cada i de 1 a 3, crea una lista con i*j para j de 1 a 3″. El bucle externo controla las filas; el interno controla los valores dentro de la fila.

Hermanas de las list comprehensions

Python tiene la misma sintaxis para crear otros tipos de colecciones.

Dict comprehension

Para construir diccionarios:

nombres = ["ana", "pedro", "luis"]

# Diccionario nombre → longitud
longitudes = {n: len(n) for n in nombres}
print(longitudes)  # {'ana': 3, 'pedro': 5, 'luis': 4}

# Invertir un diccionario
edades = {"Ana": 30, "Pedro": 25, "Luis": 40}
invertido = {edad: nombre for nombre, edad in edades.items()}
print(invertido)  # {30: 'Ana', 25: 'Pedro', 40: 'Luis'}

Set comprehension

Para construir sets (conjuntos sin duplicados):

texto = "el pythonista"

# Letras únicas (sin espacios)
letras = {c for c in texto if c != " "}
print(letras)  # {'e', 'l', 'p', 'y', 't', 'h', 'o', 'n', 'i', 's', 'a'}

Generator expression (la “list comprehension” con paréntesis)

Cambias [] por () y tienes un generador — un iterable perezoso que no construye la lista entera en memoria:

numeros = range(1_000_000)

# List comprehension: crea lista entera en memoria (8 MB+)
suma_lista = sum([n ** 2 for n in numeros])

# Generator expression: genera valor a valor, casi cero memoria
suma_gen = sum(n ** 2 for n in numeros)

Cuando el resultado lo vas a consumir solo una vez (sumar, contar, pasar a max/min/any/all), usa generator. Cuando necesitas la lista para algo más (acceso por índice, recorrer dos veces…), usa list.

Cuándo NO usar list comprehensions

Aquí va la parte que casi nadie cuenta. Las comprehensions son una herramienta — no la solución a todo. Hay 3 casos en los que un bucle clásico es mejor:

1. Cuando hay efectos secundarios

Si solo quieres ejecutar algo por cada elemento (imprimir, escribir en un fichero, mandar a una API), NO uses comprehension. Genera una lista que tiras a la basura.

# MAL: creas una lista de Nones para nada
[print(n) for n in [1, 2, 3]]

# BIEN
for n in [1, 2, 3]:
    print(n)

2. Cuando hay lógica de varias líneas

Si tu expresión necesita varias líneas, try/except, o múltiples if anidados, un bucle es más legible:

# MAL: ilegible, todo apretado
resultados = [parsear(x) for x in datos if x.startswith("v") and len(x) > 3 and x not in vistos]

# MEJOR: bucle clásico
resultados = []
for x in datos:
    if not x.startswith("v"):
        continue
    if len(x) <= 3:
        continue
    if x in vistos:
        continue
    resultados.append(parsear(x))

3. Cuando anidas más de 2 for

Una comprehension con 3 niveles anidados es ilegible. Punto. Bucle clásico, fin de la discusión.

Errores típicos

Tres clásicos que cometen todos los principiantes (yo el primero):

# 1. Olvidar el else en el ternario
# MAL: SyntaxError
[x if x > 0 for x in numeros]

# BIEN: con else
[x if x > 0 else 0 for x in numeros]


# 2. Usar la variable del bucle fuera de la comprehension
[n*2 for n in range(5)]
print(n)  # En Python 3 esto da NameError. En Python 2 ¡estaba en scope!


# 3. Asumir que es siempre más rápido
# Una comprehension simple suele serlo, pero no por arte de magia.
# Si dentro llamas a una función pesada, será igual de lento que un for.

Resumen rápido

Quiero…Sintaxis
Lista a partir de iterable[expr for x in iterable]
Lista filtrada[expr for x in iterable if cond]
Lista con transformación condicional[a if cond else b for x in iterable]
Diccionario{k: v for x in iterable}
Set{expr for x in iterable}
Generador (lazy)(expr for x in iterable)

Y la regla de oro: si la comprehension cabe cómoda en una línea legible, úsala. Si no, vuelve al bucle. No es estilo viejo — es código mantenible.

¿Te ha valido esto?

Si te ha resultado útil, llévate el cheatsheet de Python en PDF — 6 páginas con tipos, condicionales, bucles, estructuras de datos, funciones y los errores típicos. Para tener al lado mientras programas. Gratis.

Sin spam. Email + cheatsheet + un correo por semana con tutoriales nuevos.

Tu siguiente paso

Si has llegado hasta aquí, ya manejas list comprehensions mejor que el 70% de la gente que escribe Python. El siguiente paso es practicarlas en código real: cada vez que vayas a hacer un bucle con append, párate un segundo y pregúntate si una comprehension lo expresa mejor. La mitad de las veces, sí.

Si quieres aprender Python desde la base con ejemplos prácticos como los de esta entrada — incluyendo bucles, listas, comprehensions, dict, sets y todo lo que necesitas para escribir código Python de verdad — te lo enseño paso a paso en El Pythonista.

Un abrazo,
Oscar

¿Quieres aprender Python en orden, no a saltos?

Esto que has leído es solo una pieza. En El Pythonista lo verás todo encadenado: 11 módulos, 37+ horas de vídeo, 734 actividades y un proyecto real (MovieTracker) que crece contigo desde la primera variable hasta el deploy a producción.

Ver el curso completo →

37+ horas · 734 actividades · Proyecto real · Acceso de por vida · 14 días de garantía

Compartir

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Publicar un comentario