# ─────────────────────────────────────────────
# COMPRENSIÓN DE LISTAS (List Comprehensions)
# ─────────────────────────────────────────────
# Es una forma compacta de crear una lista nueva a partir de otra.
# Sintaxis básica:
#
# nueva_lista = [expresion for elemento in iterable]
#
# Equivale exactamente a:
#
# nueva_lista = []
# for elemento in iterable:
# nueva_lista.append(expresion)
# ─────────────────────────────────────────────
# TRANSFORMACIÓN: aplicar una operación a cada elemento
# ─────────────────────────────────────────────
lista = [1, 2, 3, 4, 5, 6]
# Por cada número de la lista, guardamos ese número multiplicado por 2
dobles = [numero * 2 for numero in lista]
print(dobles) # → [2, 4, 6, 8, 10, 12]
# 💡 EQUIVALENTE con for tradicional (hace exactamente lo mismo):
dobles = []
for numero in lista:
dobles.append(numero * 2)
# ─────────────────────────────────────────────
# TRANSFORMAR CADENAS
# ─────────────────────────────────────────────
alumnos = ["ana", "jUAN", "pep", "IU", "Eva"]
# .title() pone en mayúscula la primera letra de cada palabra y el resto en minúscula
alumnos_bien = [alumno.title() for alumno in alumnos]
print(alumnos_bien) # → ['Ana', 'Juan', 'Pep', 'Iu', 'Eva']
# 💡 ALTERNATIVAS a .title() para normalizar texto:
# "jUAN".upper() → "JUAN" todo mayúsculas
# "jUAN".lower() → "juan" todo minúsculas
# "jUAN".capitalize() → "Juan" solo la primera letra en mayúscula
# "jUAN".title() → "Juan" mayúscula al inicio de cada palabra
# [0:2] → slice con los dos primeros caracteres de cada nombre
alumnos_comienzos = [alumno[0:2] for alumno in alumnos]
print(alumnos_comienzos) # → ['an', 'jU', 'pe', 'IU', 'Ev']
# ─────────────────────────────────────────────
# USAR EL ELEMENTO COMO CANTIDAD
# ─────────────────────────────────────────────
lista = [2, 4, 5, 3]
# El número indica cuántas veces repetimos el carácter "*"
# "*" * 3 → "***"
asteriscos = ["*" * n for n in lista]
print(asteriscos) # → ['**', '****', '*****', '***']
# 💡 ALTERNATIVA: usar otro carácter o construir una barra de progreso
barras = ["█" * n for n in lista]
print(barras) # → ['██', '████', '█████', '███']
# ─────────────────────────────────────────────
# COMBINAR SLICE Y COMPRENSIÓN
# ─────────────────────────────────────────────
letras = "abcdefghijklmnopqrstuvwxyz"
# Para cada n de la lista, tomamos los primeros n caracteres del abecedario
# letras[0:2] → "ab" | letras[0:4] → "abcd" | letras[0:5] → "abcde"
comienzos = [letras[0:n] for n in lista]
print(comienzos) # → ['ab', 'abcd', 'abcde', 'abc']
# ─────────────────────────────────────────────
# COPIA DE UNA LISTA
# ─────────────────────────────────────────────
# Si la expresión es simplemente el propio elemento, obtenemos una copia
lista_igual = [n for n in lista]
print(lista_igual) # → [2, 4, 5, 3]
# 💡 ALTERNATIVA más directa para copiar una lista:
# lista_igual = lista.copy()
# lista_igual = lista[:]
# ─────────────────────────────────────────────
# FILTRADO: añadir una condición con 'if'
# ─────────────────────────────────────────────
# Sintaxis con filtro:
#
# nueva_lista = [expresion for elemento in iterable if condicion]
#
# Solo se incluyen los elementos que cumplen la condición.
palabras = ["patata", "bustrofedónico", "alubia",
"otorrinolaringólogo", "mesa", "supercalifragilísticoespialidoso"]
# Solo incluimos la palabra si su longitud (len) es mayor de 10
palabras_largas = [palabra for palabra in palabras if len(palabra) > 10]
print(palabras_largas) # → ['bustrofedónico', 'otorrinolaringólogo', 'supercalifragilísticoespialidoso']
# 💡 ALTERNATIVAS de filtrado:
palabras_cortas = [p for p in palabras if len(p) <= 5] # longitud ≤ 5
con_a = [p for p in palabras if p.startswith('a')] # que empiecen por 'a'
con_vocal_final = [p for p in palabras if p[-1] in 'aeiou'] # acaban en vocal
# ─────────────────────────────────────────────
# COMBINAR FILTRADO Y TRANSFORMACIÓN
# ─────────────────────────────────────────────
# La expresión y la condición pueden ser distintas:
# · la condición decide SI se incluye el elemento
# · la expresión decide QUÉ se guarda de ese elemento
# Objetivo: de una lista de nombres, quedarse solo con los de
# longitud PAR e invertirlos.
# ["Pep","Iu","Eva","Juan"] → longitud par: "Iu"(2), "Juan"(4) → invertidos: ["uI","nauJ"]
lista = ["Pep", "Iu", "Eva", "Juan"]
# Paso a paso:
# 1. if len(i) % 2 == 0 → filtra: solo "Iu" y "Juan" tienen longitud par
# 2. i[::-1] → transforma: invierte cada cadena seleccionada
par_invertidas = [i[::-1] for i in lista if len(i) % 2 == 0]
print(par_invertidas) # → ['uI', 'nauJ']
# 💡 EQUIVALENTE con for tradicional, más explicado:
par_invertidas = []
for i in lista:
if len(i) % 2 == 0: # condición: longitud par
par_invertidas.append(i[::-1]) # transformación: invertir
# 💡 ALTERNATIVA: guardar también el original para comparar
pares_con_original = [(i, i[::-1]) for i in lista if len(i) % 2 == 0]
print(pares_con_original) # → [('Iu', 'uI'), ('Juan', 'nauJ')]
Anatomía de una comprensión de lista
resultado = [ expresión for elemento in iterable if condición ]
│ │ │ │
│ │ │ └── (opcional) filtro:
│ │ │ solo los que cumplan esto
│ │ └─────────────── de dónde vienen los datos
│ └───────────────────────────── nombre temporal
└────────────────────────────────────────────── qué guardamos
Comparativa: for tradicional vs comprensión
Con for tradicional |
Con comprensión |
|---|---|
resultado = [] + for + append() |
Todo en una línea |
| Más fácil de leer al principio | Más compacto y expresivo |
| Fácil de depurar paso a paso | Ideal cuando la lógica es simple |
| Mejor si hay lógica compleja | Evitar si hay más de una condición |
Los tres sabores de la comprensión
# 1. Solo transformación
[expresion for x in lista]
# 2. Solo filtrado
[x for x in lista if condicion]
# 3. Transformación + filtrado
[expresion for x in lista if condicion]
💡 Regla de oro: si el
for+ifcabe en una línea corta y se lee de forma natural, usa comprensión. Si necesitas anidar dosfor, añadir variosifo la lógica es compleja, elfortradicional será más claro y fácil de mantener.