📘 Lección 4.5 — Comprehensions en Python
- Parte 1 — Introducción a las Comprehensions y List Comprehensions
- Parte 2 — Dict Comprehensions (diccionarios)
- Parte 3 — Set Comprehensions (conjuntos)
- Parte 4 — Condicionales en Comprehensions
- Parte 5 — Comprehensions anidadas, rendimiento y optimización
Haz clic en cada parte para navegar directamente. Cada sección está diseñada para estudiantes principiantes, con ejemplos visuales, código comentado y comparaciones con bucles tradicionales.
Parte 1 — Introducción a las Comprehensions y List Comprehensions
Objetivo: entender qué son las comprensiones (comprehensions) en Python, por qué simplifican el código y cómo crear listas de forma elegante, legible y eficiente.
1) ¿Qué son las comprehensions?
Las comprehensions (comprensiones) son una forma concisa y expresiva de crear estructuras de datos como listas, diccionarios o conjuntos directamente a partir de iterables.
Permiten reemplazar bucles for
y condicionales if
sencillos con una sola línea legible, manteniendo la semántica pero mejorando el rendimiento y la claridad.
# Sin comprehension:
cuadrados = []
for n in range(5):
cuadrados.append(n ** 2)
# Con list comprehension:
cuadrados = [n ** 2 for n in range(5)]
print(cuadrados) # [0, 1, 4, 9, 16]
Ambas versiones hacen lo mismo, pero la comprensión reduce el código en más del 60%, mejora la legibilidad y elimina la necesidad de llamar a append()
explícitamente.
[expresión for elemento in iterable]
.2) Estructura general de una List Comprehension
La sintaxis básica de una comprensión de lista es:
[expresión for elemento in iterable]
Donde:
Componente | Descripción | Ejemplo |
---|---|---|
expresión | Transformación o valor que se añade a la lista. | n ** 2 |
elemento | Variable que toma cada valor del iterable. | n |
iterable | Cualquier objeto que se pueda recorrer con for (lista, rango, cadena, etc.). | range(5) |
En otras palabras, Python itera sobre iterable
, aplica la expresión
a cada elemento
y agrega el resultado a la nueva lista.
# Crear una lista de cubos
cubos = [n ** 3 for n in range(1, 6)]
print(cubos) # [1, 8, 27, 64, 125]
3) Comparación entre bucle tradicional y comprensión
Versión tradicional | Versión con comprensión |
---|---|
|
|
Ambas generan la lista [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
, pero la segunda es más legible, idiomática y pythonic.
4) Ejemplos comunes de List Comprehensions
4.1 Generar listas numéricas
# Lista de los primeros 10 números pares
pares = [n for n in range(20) if n % 2 == 0]
print(pares) # [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
4.2 Convertir cadenas a mayúsculas
nombres = ["ana", "carlos", "elena"]
nombres_mayus = [nombre.upper() for nombre in nombres]
print(nombres_mayus) # ['ANA', 'CARLOS', 'ELENA']
4.3 Calcular longitudes de palabras
palabras = ["python", "código", "abierto"]
longitudes = [len(p) for p in palabras]
print(longitudes) # [6, 6, 7]
4.4 Filtrar con condicional
# Números divisibles entre 3
div_3 = [n for n in range(1, 20) if n % 3 == 0]
print(div_3) # [3, 6, 9, 12, 15, 18]
4.5 Transformar con expresiones más complejas
# Elevar al cuadrado los números impares
impares_cuadrado = [n ** 2 for n in range(10) if n % 2 != 0]
print(impares_cuadrado) # [1, 9, 25, 49, 81]
5) Ventajas de usar comprehensions
Ventaja | Descripción |
---|---|
Concisión | Reemplazan varios renglones de código con una sola línea. |
Claridad | Expresan directamente la intención: “quiero una lista de esto, a partir de esto”. |
Rendimiento | Son más rápidas que los bucles for convencionales al evitar múltiples llamadas a append() . |
Pythonicidad | Es la forma idiomática recomendada por la comunidad y el Zen de Python (“Beautiful is better than ugly”). |
6) Mini ejercicios prácticos
- Crea una lista con los cuadrados de los números del 1 al 10.
cuadrados = [n ** 2 for n in range(1, 11)] print(cuadrados)
- Genera una lista con los caracteres de una cadena en mayúsculas.
texto = "python" letras = print(letras)
- Obtén una lista de los múltiplos de 5 entre 1 y 50.
multiplos_5 = [n for n in range(1, 51) if n % 5 == 0] print(multiplos_5)
7) Resumen ejecutivo
- Las comprehensions son expresiones concisas para crear listas, diccionarios o conjuntos.
- La estructura base es
[expresión for elemento in iterable]
. - Pueden incluir condicionales y anidamientos.
- Son más legibles, rápidas y “pythónicas”.
- Perfectas para reemplazar bucles simples que construyen listas.
Parte 2 — Dict Comprehensions (diccionarios)
Objetivo: aprender a generar diccionarios
en una sola línea utilizando comprensiones, creando pares clave–valor a partir de datos iterables o transformaciones.
1) Introducción a las Dict Comprehensions
Una Dict Comprehension (comprensión de diccionario) es una construcción sintáctica de Python que permite crear un diccionario
en una sola línea, de forma similar a las List Comprehensions
, pero generando pares clave:valor.
Su estructura general es:
{clave: valor for elemento in iterable}
Python recorre el iterable
, evalúa la expresión de clave
y valor
para cada elemento y construye un diccionario con ellos.
# Ejemplo básico: crear un diccionario con los cuadrados de 1 a 5
cuadrados = {n: n**2 for n in range(1, 6)}
print(cuadrados)
# {1: 1, 2: 4, 3: 9, 4: 16, 5: 25}
clave:valor
, y las claves deben ser únicas.2) Comparación: bucle tradicional vs Dict Comprehension
Versión tradicional | Dict Comprehension |
---|---|
|
|
La segunda versión es más legible, elimina la necesidad de inicializar el diccionario y evita el uso explícito de .update()
o []
.
3) Aplicaciones comunes de Dict Comprehensions
3.1 Invertir claves y valores
# Intercambiar claves y valores en un diccionario
monedas = {"USD": "Dólar", "EUR": "Euro", "JPY": "Yen"}
invertido = {valor: clave for clave, valor in monedas.items()}
print(invertido)
# {'Dólar': 'USD', 'Euro': 'EUR', 'Yen': 'JPY'}
Útil para: búsquedas inversas o intercambio de roles entre clave–valor.
3.2 Transformar valores
precios_usd = {"manzana": 1, "banana": 0.5, "pera": 0.75}
# Convertir precios a euros
precios_eur = {fruta: precio * 0.9 for fruta, precio in precios_usd.items()}
print(precios_eur)
# {'manzana': 0.9, 'banana': 0.45, 'pera': 0.675}
3.3 Filtrar datos en el diccionario
# Filtrar solo frutas con precio > 0.6
caro = {f: p for f, p in precios_usd.items() if p > 0.6}
print(caro)
# {'manzana': 1, 'pera': 0.75}
Puedes incluir condicionales al final (al igual que en las list comprehensions) para filtrar los elementos que serán incluidos.
4) Dict Comprehensions a partir de otras estructuras
También puedes generar diccionarios desde listas, tuplas o cualquier iterable. Esto resulta muy útil para transformar datos.
# Crear un diccionario a partir de dos listas paralelas
claves = ["nombre", "edad", "ciudad"]
valores = ["Ana", 25, "Madrid"]
persona = {k: v for k, v in zip(claves, valores)}
print(persona)
# {'nombre': 'Ana', 'edad': 25, 'ciudad': 'Madrid'}
La función zip()
combina elementos de ambas listas, y la comprensión construye el diccionario clave–valor automáticamente.
5) Ejemplos prácticos
5.1 Crear un diccionario de longitudes de palabras
palabras = ["python", "comprehension", "código", "curso"]
longitudes = {p: len(p) for p in palabras}
print(longitudes)
# {'python': 6, 'comprehension': 13, 'código': 6, 'curso': 5}
5.2 Generar un diccionario de números y su paridad
paridad = {n: ("par" if n % 2 == 0 else "impar") for n in range(1, 6)}
print(paridad)
# {1: 'impar', 2: 'par', 3: 'impar', 4: 'par', 5: 'impar'}
5.3 Normalizar texto en claves
# Normalizar claves a minúsculas
datos = {"Nombre": "Ana", "Ciudad": "Madrid", "PAÍS": "España"}
normalizado = {k.lower(): v for k, v in datos.items()}
print(normalizado)
# {'nombre': 'Ana', 'ciudad': 'Madrid', 'país': 'España'}
6) Tabla resumen de sintaxis
Patrón | Descripción | Ejemplo |
---|---|---|
{k:v for k,v in iterable} | Básico: crea pares clave–valor. | {x:x**2 for x in range(5)} |
{k:v for k,v in iterable if cond} | Incluye solo los elementos que cumplen la condición. | {f:p for f,p in precios if p>1} |
{exp1:exp2 for ...} | Permite expresiones complejas para transformar. | {k.upper():v*2 for k,v in d.items()} |
7) Ejercicios prácticos
- Crea un diccionario con los números del 1 al 5 como claves y sus cubos como valores.
cubos = {n: n**3 for n in range(1, 6)} print(cubos)
- A partir de una lista de nombres, crea un diccionario que mapee cada nombre con su longitud.
nombres = ["Ana", "Carlos", "Beatriz"] longitudes = {n: len(n) for n in nombres} print(longitudes)
- Dado un diccionario de temperaturas en °C, genera otro en °F.
celsius = {"Madrid": 20, "Sevilla": 30, "Bilbao": 18} fahrenheit = {ciudad: (temp * 9/5) + 32 for ciudad, temp in celsius.items()} print(fahrenheit)
8) Resumen ejecutivo
- Las Dict Comprehensions crean diccionarios con una sola expresión:
{clave: valor for ...}
. - Pueden incluir condicionales, expresiones y funciones.
- Evitan bucles largos y mejoran la legibilidad del código.
- Se pueden combinar con
zip()
o.items()
para transformar datos fácilmente.
Parte 3 — Set Comprehensions (conjuntos)
Objetivo: crear set
(conjuntos) en una sola línea para eliminar duplicados, filtrar y transformar datos con sintaxis concisa y rendimiento sólido.
1) ¿Qué es una Set Comprehension?
Una Set Comprehension genera un set
aplicando una expresión a cada elemento de un iterable.
Al ser conjuntos, los resultados son únicos y el contenedor no garantiza orden. Es perfecta para
deduplicar a la vez que transformas/filtras.
# Bucle tradicional
cuadrados = set()
for n in range(5):
cuadrados.add(n ** 2)
# Set comprehension (equivalente y más concisa)
cuadrados = {n ** 2 for n in range(5)}
print(cuadrados) # {0, 1, 4, 9, 16}
{expresión for elemento in iterable}
para producir un conjunto único sin duplicados.2) Sintaxis básica y con condición
2.1 Forma base
{expresion for item in iterable}
2.2 Con filtrado (if
)
{expresion for item in iterable if condicion}
# Cuadrados de los pares entre 0 y 9
pares_cuadrados = {n ** 2 for n in range(10) if n % 2 == 0}
print(pares_cuadrados) # {0, 4, 16, 36, 64}
Patrón idéntico al mostrado en list comprehensions, pero el resultado es un set
.
3) Casos de uso típicos
3.1 Deduplicar mientras transformas
# Eliminar duplicados y quedarnos con primeras letras únicas
palabras = ["manzana", "banana", "mango", "melón", "mora", "naranja"]
primeras = {p[0] for p in palabras}
print(primeras) # {'m', 'b', 'n'}
Útil cuando te interesa el conjunto de valores sin repeticiones.
3.2 Filtrado de datos únicos
# Vocales únicas presentes en un texto
texto = "python es un lenguaje de programación versátil"
vocales = {c for c in texto.lower() if c in "aeiou"}
print(vocales) # {'a', 'e', 'i', 'o', 'u'}
3.3 Transformación rápida con eliminación de duplicados
# Longitudes únicas de palabras
palabras = ["casa", "perro", "sol", "luna", "mar", "montaña"]
longitudes_unicas = {len(p) for p in palabras}
print(longitudes_unicas) # {3, 4, 5, 7}
3.4 Operaciones sobre conjuntos (combinación)
A = {1, 2, 3, 4, 5}
B = {4, 5, 6, 7, 8}
# Duplicar elementos de la unión
union_doble = {x * 2 for x in A.union(B)}
print(union_doble) # {2, 4, 6, 8, 10, 12, 14, 16}
# Elevar al cuadrado elementos de la intersección
intersec_cuad = {x ** 2 for x in A.intersection(B)}
print(intersec_cuad) # {16, 25}
Puedes mezclar comprehensions con métodos/operadores de conjuntos sin problema.
4) Notas importantes (orden, hashabilidad y pertenencia)
- Sin orden ni índice: un
set
no mantiene orden; si necesitas orden estable, usa list comprehension y ordena después. - Elementos hashables: solo tipos inmutables (números,
str
, tuplas…); listas o dicts daránTypeError
. - Búsquedas rápidas: comprobar pertenencia
x in s
es muy eficiente, ideal para filtros y deduplicación.
# Mantener orden y eliminar duplicados (truco complementario si luego quieres lista ordenable)
numeros = [5, 2, 3, 1, 4, 3]
sin_dupes_preservando_orden = list(dict.fromkeys(numeros))
print(sin_dupes_preservando_orden) # [5, 2, 3, 1, 4]
5) Mini casos reales
5.1 Productos únicos comprados
compras = [
{"cliente": "Ana", "producto": "laptop"},
{"cliente": "Juan", "producto": "teléfono"},
{"cliente": "Ana", "producto": "auriculares"},
{"cliente": "Pedro", "producto": "laptop"},
{"cliente": "Juan", "producto": "auriculares"},
{"cliente": "Ana", "producto": "teléfono"},
]
productos_unicos = {c["producto"] for c in compras}
print(productos_unicos) # {'laptop', 'teléfono', 'auriculares'}
5.2 Clientes que compraron un producto
compradores_laptop = {c["cliente"] for c in compras if c["producto"] == "laptop"}
print(compradores_laptop) # {'Ana', 'Pedro'}
5.3 Iniciales únicas de clientes
iniciales = {c["cliente"][0] for c in compras}
print(iniciales) # {'A', 'J', 'P'}
Estos patrones vienen tal cual de tu referencia sobre set comprehensions.
6) Rendimiento y cuándo usarlas
- Al crear conjuntos, las comprehensions son concisas y suelen ser eficientes frente a bucles con
add()
por iteración. - Son idóneas si necesitas a la vez transformar y quitar duplicados.
- Si el conjunto resultante va a ser muy grande y solo quieres iterar por él una vez, considera un generador antes de convertir a
set
(para escalabilidad).
7) Tabla rápida de sintaxis
Patrón | Qué hace | Ejemplo |
---|---|---|
{exp for x in it} | Crea un set transformando cada elemento. | {x*x for x in range(5)} |
{exp for x in it if cond} | Filtra con condición. | {x for x in nums if x%2==0} |
{f(y) for y in A|B} | Combina con operaciones de conjuntos. | {y*2 for y in A.union(B)} |
8) Mini-retos (5′)
- Extrae las vocales únicas de
"Aprender Python es divertido"
(en minúscula).texto = "Aprender Python es divertido" vocales = {c for c in texto.lower() if c in "aeiou"} print(vocales)
- Crea un set con los cuadrados únicos de los números entre 1 y 30 que sean múltiplos de 3.
cuadrados = {n**2 for n in range(1,31) if n % 3 == 0} print(cuadrados)
- Dadas palabras con repeticiones, obtén las longitudes únicas de las que empiezan por “p”.
palabras = ["python","poema","playa","python","piedra","sol"] lens_p = {len(p) for p in palabras if p.startswith("p")} print(lens_p)
9) Resumen ejecutivo
- Set comprehension:
{exp for item in iterable [if cond]}
. - Ideal para unicidad + transformación/filtrado en una pasada.
- Sin orden ni índice; elementos deben ser hashables.
- Se integra de forma natural con operaciones de conjuntos (
union
,intersection
…).
Parte 4 — Condicionales en Comprehensions
Objetivo: dominar el uso de condiciones dentro de list/dict/set comprehensions para filtrar y transformar datos de forma limpia, legible y eficiente.
1) Dos modos de “meter lógica” en una comprehension
Hay dos ubicaciones con propósitos distintos:
- Filtro (después del
for
): incluye o excluye elementos.[exp for x in it <u>if cond(x)</u>]
- Condicional en la expresión (ternario): elige el valor que se agrega.
[<u>exp_true if cond(x) else exp_false</u> for x in it]
for
filtras; antes del for
(en la “expresión”) decides qué valor producir.2) Filtro con if
(al final)
Sirve para seleccionar los elementos que entran en el resultado.
# Números pares entre 0 y 9 (solo se incluyen los que cumplen)
pares = [n for n in range(10) if n % 2 == 0]
print(pares) # [0, 2, 4, 6, 8]
Este patrón existe por igual para list, dict y set comprehensions y es central en tu referencia.
Colección | Patrón de filtro | Ejemplo |
---|---|---|
Lista | [exp for x in it if cond] | [w.upper() for w in palabras if w.isalpha()] |
Set | {exp for x in it if cond} | {len(w) for w in palabras if w.startswith("p")} |
Dict | {k:v for k,v in it if cond} | {k:v for k,v in d.items() if v > 0} |
3) Condicional ternario en la expresión (A if cond else B
)
Se usa para elegir el valor que se va a producir por elemento (no para filtrar).
# Etiqueta "par"/"impar" para números 1..6 (nadie se filtra)
paridad = ["par" if n % 2 == 0 else "impar" for n in range(1, 7)]
print(paridad) # ['impar','par','impar','par','impar','par']
# Dict comprehension con ternario en el valor
precios = {"manzana": 1.0, "banana": 0.5, "pera": 1.2}
clasif = {f: ("caro" if p >= 1.0 else "barato") for f, p in precios.items()}
print(clasif) # {'manzana': 'caro', 'banana': 'barato', 'pera': 'caro'}
Tu PDF muestra este uso como forma idiomática de transformar valores según condiciones simples.
4) Múltiples condiciones y composición
4.1 Encadenar filtros
# Pares mayores que 10
resultado = [n for n in range(30) if n % 2 == 0 if n > 10]
print(resultado) # [12, 14, 16, 18, 20, 22, 24, 26, 28]
4.2 Condiciones compuestas (and/or)
# Múltiplos de 3 o 5, pero no de ambos
nums = [n for n in range(1, 50) if (n % 3 == 0) ^ (n % 5 == 0)]
print(nums)
4.3 Ternario + filtro
# Formatear números >= 1000 con separador; descartar negativos
datos = ["{:,}".format(n) if n >= 1000 else str(n)
for n in [1200, 50, -3, 5_000, 999]
if n >= 0]
print(datos) # ['1,200', '50', '5,000', '999']
5) Casos prácticos (list/dict/set)
5.1 Limpieza básica de texto (list)
# Mantener palabras alfanuméricas y normalizarlas
texto = "Python, es #genial y muy versátil!"
tokens = [w.lower() for w in texto.replace(",", "").split() if w.isalpha() or w.isalnum()]
print(tokens)
5.2 Filtrado de inventario (dict)
stock = {"manzanas": 12, "plátanos": 0, "naranjas": 25, "peras": 3}
disponibles = {k: v for k, v in stock.items() if v > 0}
print(disponibles) # {'manzanas': 12, 'naranjas': 25, 'peras': 3}
5.3 Vocales únicas en una frase (set)
frase = "python es un lenguaje de programación versátil"
vocales = {c for c in frase.lower() if c in "aeiou"}
print(vocales) # {'a', 'e', 'i', 'o', 'u'}
Estos patrones (filtrado y extracción) están alineados con los casos de uso del PDF.
6) Antipatrones y cómo evitarlos
- Comprehensions kilométricas: si hay demasiadas condiciones/ternarios, pasa a un
for
normal conif
anidados. Legibilidad primero. - Trabajo pesado en la condición: evita recomputar funciones caras dentro del
if
; guarda en variables previas o usa funciones auxiliares. - Abusar del ternario: uno anidado es tolerable; múltiples ternarios → refactoriza.
- Orden en set comprehensions: no confíes en él; si importa, usa lista +
sorted()
.
7) Rendimiento y memoria (quick wins)
- Las comprehensions suelen ser más rápidas que los bucles con
append/add/asignación
por su implementación interna y menor sobrecarga. - Para colecciones muy grandes donde solo necesitas iterar una vez, considera generadores (
(exp for x in it)
) y convertir a lista/set más tarde. - Filtrar primero, transformar después: a menudo es más barato (menos evaluaciones de la expresión de salida).
# Generador + conversión tardía (memoria-friendly)
gen = (n for n in range(1_000_000) if n % 10 == 0)
muestra = list(next(gen) for _ in range(5)) # consumir poco a poco
print(muestra)
8) Micro-retos (5′)
- Genera
["PAR", "IMPAR", ...]
para 1..12 (sin filtrar, usa ternario).etq = ["PAR" if n % 2 == 0 else "IMPAR" for n in range(1, 13)] print(etq)
- De una lista de tuplas
(nombre, edad)
, arma un dict solo con mayores de 18.personas = [("Ana", 17), ("Carlos", 21), ("Elena", 19)] mayores = {n: e for (n, e) in personas if e >= 18} print(mayores)
- Extrae un set con longitudes únicas de palabras que empiecen por “a” u “o”.
palabras = ["agua", "oso", "python", "ala", "sol", "ola"] lens_unicas = {len(p) for p in palabras if p[0] in {"a","o"}} print(lens_unicas)
9) Resumen ejecutivo
- Filtro:
... for x in it if cond
incluye/excluye elementos. - Ternario:
exp_true if cond else exp_false
decide el valor que se añade. - Combínalos con moderación; si la lógica crece, cambia a bucles claros.
- Aplica generadores cuando el volumen de datos sea enorme.
Parte 5 — Comprensiones anidadas y optimización
Objetivo: dominar comprensiones anidadas (listas, diccionarios y conjuntos), aplicarlas a casos reales (matrices, flatten, producto cartesiano) y optimizarlas sin sacrificar legibilidad.
1) Comprensiones anidadas: la base
Una comprensión anidada usa varios for
(y opcionalmente condiciones) dentro de la misma expresión. Útil para transformar estructuras 2D, generar combinaciones, o aplanar colecciones. Mantén la lógica simple para no perder legibilidad.
# Lista de pares (i, j) con i in [0..2], j in [0..2]
pares = [(i, j) for i in range(3) for j in range(3)]
print(pares) # [(0,0),(0,1),(0,2),(1,0)...]
i
en range(3)
, por cada j
en range(3)
, produce (i, j)
”. Si la lectura cuesta, rompe en pasos.2) Flatten (aplanar listas de listas)
Patrón clásico para pasar de 2D → 1D. Si la estructura es muy profunda o la lógica compleja, alterna con funciones auxiliares.
matriz = [[1, 2, 3], [4, 5], [6]]
aplanado = [x for fila in matriz for x in fila]
print(aplanado) # [1,2,3,4,5,6]
Con condición (solo pares):
aplanado_pares = [x for fila in matriz for x in fila if x % 2 == 0]
print(aplanado_pares) # [2, 4, 6]
3) Matrices: mapeos y transposición
Transforma cada celda con una expresión, o transpón una matriz con zip + comprensión.
# Incrementar cada celda
M = [[1, 2], [3, 4]]
M_inc = [ for fila in M]
print(M_inc) # [[2,3],[4,5]]
# Transponer (columnas<->filas)
M_T = [ for col in zip(*M)]
print(M_T) # [[1,3],[2,4]]
transform(c)
y úsala dentro de la comprensión.4) Producto cartesiano y combinaciones
Genera combinaciones ordenadas entre dos colecciones, aplicando filtros in-line si procede.
tallas = ["S", "M", "L"]
colores = ["rojo", "azul"]
combos = [(t, c) for t in tallas for c in colores]
print(combos) # [('S','rojo'),('S','azul'),('M','rojo'),...]
# Filtrar al vuelo
combos_filtrados = [(t, c) for t in tallas for c in colores if not (t == "S" and c == "rojo")]
5) Dict y Set comprehensions anidadas
También puedes anidar en diccionarios y conjuntos. Útil para indexar, agrupar o deduplicar con transformación.
5.1 Índice invertido simple (dict)
docs = [
{"id": 1, "tags": ["python", "linux"]},
{"id": 2, "tags": ["python", "datos"]},
]
indice = {tag: {d["id"] for d in docs if tag in d["tags"]}
for tag in {t for d in docs for t in d["tags"]}}
print(indice) # {'linux':{1}, 'python':{1,2}, 'datos':{2}}
5.2 Diccionario a partir de pares (clave única + transformación)
pares = [("ana", 8.5), ("carlos", 7.2), ("ana", 9.0)]
# Último valor gana si hay claves duplicadas (propio de dict)
notas = {k: v for (k, v) in pares}
print(notas) # {'ana': 9.0, 'carlos': 7.2}
5.3 Set anidado: longitudes únicas por inicial
palabras = ["perro","piedra","gato","guitarra","piano"]
longitudes_por_inicial = {
inicial: {len(w) for w in palabras if w.startswith(inicial)}
for inicial in {w[0] for w in palabras}
}
print(longitudes_por_inicial) # {'p':{5,6}, 'g':{4,8}}
6) Condicionales en comprensiones anidadas
Combina filtro y ternario de forma controlada. Si la expresión se vuelve densa, usa funciones auxiliares o bucles.
# Etiquetar celdas >=10 como "OK", descartar negativas
mat = [[-1, 5, 12], [0, 14, 3]]
etiquetas = [["OK" if c >= 10 else "LOW" for c in fila if c >= 0] for fila in mat]
print(etiquetas) # [['LOW','OK'], ['LOW','OK','LOW']]
for
+ varias condiciones + ternarios anidados = deuda técnica. Prioriza claridad; el PDF recomienda simplicidad y buen juicio.7) Optimización: performance y memoria
- Comprehension vs bucle: suelen ser más rápidas que bucles con
append()
/add()
por menor sobrecarga de Python. - Generadores: para flujos muy grandes, usa generator expressions y materializa al final si necesitas lista/set.
- Filtra pronto: coloca el
if
de filtro lo antes posible; reduces trabajo aguas abajo. - Evita recomputar: factoriza cálculos costosos en variables o funciones auxiliares fuera de la comprensión.
- Uso de
zip
/dict.fromkeys
: resuelven casos comunes de unión/deduplicación con coste bajo y buen estilo.
# Generador + materialización tardía
gen = (n*n for n in range(1_000_000) if n % 10 == 0) # memoria O(1)
top5 = [next(gen) for _ in range(5)]
print(top5)
8) Tabla de patrones (cheatsheet)
Patrón | Qué resuelve | Ejemplo |
---|---|---|
[x for fila in M for x in fila] | Flatten 2D → 1D | aplanado = [x for f in M for x in f] |
[[f(c) for c in fila] for fila in M] | Mapeo celda a celda | M2 = [ for fila in M] |
[(a,b) for a in A for b in B] | Producto cartesiano | pairs = [(t,c) for t in T for c in C] |
{k: f(v) for k,v in d.items() if cond(v)} | Filtrar + transformar dict | caro = {k:p for k,p in d.items() if p>1} |
{g(x) for x in it if cond(x)} | Set único transformado | lens = {len(w) for w in palabras} |
9) Ejercicios (evaluación rápida)
- Flatten + filtro: dada
M = [[1, -3, 4], [0, 7], [-2, 5]]
, crea una lista con los positivos, en orden, elevados al cuadrado.
Solución
M = [[1, -3, 4], [0, 7], [-2, 5]] res = [x*x for fila in M for x in fila if x > 0] print(res) # [1,16,7*7,25]
- Transposición limpia: transpón
M = [[1,2,3],[4,5,6]]
con zip + comprensión.
Solución
M = [[1,2,3],[4,5,6]] M_T = [ for col in zip(*M)] print(M_T) # [[1,4],[2,5],[3,6]]
- Dict de conteo por inicial: de
["Ana","Alba","Luis","Lucía","Leo"]
, crea{"A":2, "L":3}
usando dos comprensiones.
Solución
nombres = ["Ana","Alba","Luis","Lucía","Leo"] iniciales = {n[0] for n in nombres} conteo = {i: sum(1 for n in nombres if n.startswith(i)) for i in iniciales} print(conteo) # {'A':2, 'L':3}
- Producto cartesiano filtrado: de tallas
S,M,L
y coloresrojo, azul, verde
, excluye("S","rojo")
.
Solución
T, C = ["S","M","L"], ["rojo","azul","verde"] combos = [(t,c) for t in T for c in C if not (t=="S" and c=="rojo")] print(combos)
- Set anidado por categoría: a partir de
[("dev","python"),("dev","linux"),("data","python")]
genera{"dev":{"python","linux"}, "data":{"python"}}
.
Solución
pares = [("dev","python"),("dev","linux"),("data","python")] cats = {cat for (cat, _) in pares} resultado = {cat: {tech for (c, tech) in pares if c == cat} for cat in cats} print(resultado)
10) Resumen ejecutivo
- Comprensiones anidadas: poderosas para 2D/3D, flatten y combinaciones; mantén la lógica simple.
- Optimiza con generadores, filtra pronto y evita recomputaciones caras.
- Si la expresión se vuelve densa, refactoriza a funciones o bucles claros: legibilidad > cleverness.