Volver a Labs
Intermedio

Colecciones en Python — Listas, Diccionarios y Comprehensions

2–3 horas Actualizado Junio 2026
Python Listas Diccionarios Comprehensions Backend

Introducción

Las colecciones son el corazón de Python. Casi cualquier programa no trivial trabaja con grupos de datos: listas de usuarios, diccionarios de configuración, conjuntos de etiquetas. Conocerlos bien marca la diferencia entre código que funciona y código que es elegante y eficiente.

Python incluye cuatro colecciones principales en la librería estándar, cada una con características propias.

¿Qué vas a aprender en este lab?

  • Listas: la colección más versátil
  • Tuplas: secuencias inmutables
  • Diccionarios: pares clave-valor
  • Conjuntos: elementos únicos
  • List, dict y set comprehensions
  • Expresiones generadoras

Requisitos previos: fundamentos de Python (variables, bucles, funciones).


1. Listas

Una lista es una secuencia ordenada y mutable de elementos de cualquier tipo.

frutas = ["manzana", "naranja", "pera"]
mixta  = [1, "hola", True, 3.14, None]

# Acceso por índice (empieza en 0, negativo desde el final)
print(frutas[0])   # manzana
print(frutas[-1])  # pera

# Slicing [inicio:fin:paso] — fin es exclusivo
print(frutas[0:2]) # ['manzana', 'naranja']
print(frutas[::-1]) # ['pera', 'naranja', 'manzana'] — invertida

Métodos principales

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

numeros.append(7)          # agrega al final: [3, 1, 4, 1, 5, 9, 2, 6, 7]
numeros.insert(0, 0)       # inserta en posición: [0, 3, 1, ...]
numeros.remove(1)          # elimina la primera ocurrencia de 1
ultimo = numeros.pop()     # elimina y devuelve el último
primero = numeros.pop(0)   # elimina y devuelve el índice 0

numeros.sort()             # ordena en su lugar
numeros.sort(reverse=True) # ordena descendente
ordenados = sorted(numeros) # devuelve copia ordenada, no modifica original

print(numeros.count(1))    # cuántas veces aparece 1
print(numeros.index(5))    # índice de la primera ocurrencia de 5
numeros.reverse()          # invierte en su lugar
copia = numeros.copy()     # copia superficial
numeros.clear()            # vacía la lista

Operaciones con listas

a = [1, 2, 3]
b = [4, 5, 6]

print(a + b)        # [1, 2, 3, 4, 5, 6] — concatenación
print(a * 3)        # [1, 2, 3, 1, 2, 3, 1, 2, 3] — repetición
print(3 in a)       # True
print(len(a))       # 3
print(sum(a))       # 6
print(min(a), max(a)) # 1, 3

# Desempaquetado
x, y, z = a
print(x, y, z)      # 1 2 3

primero, *resto = [1, 2, 3, 4, 5]
print(primero)      # 1
print(resto)        # [2, 3, 4, 5]

Ejercicio 1

Dada una lista de notas ([7.5, 8.0, 9.5, 6.0, 8.5, 7.0, 9.0]), calcula: la nota más alta, la más baja, el promedio, y devuelve una nueva lista solo con notas superiores al promedio, ordenadas de mayor a menor.


2. Tuplas

Una tupla es una secuencia ordenada e inmutable (no se puede modificar tras crearla). Son más rápidas que las listas y se usan para datos que no deben cambiar.

coordenadas = (40.7128, -74.0060)   # latitud, longitud Nueva York
rgb         = (255, 128, 0)
un_solo_elemento = (42,)             # la coma es necesaria

# Acceso igual que listas
print(coordenadas[0])   # 40.7128
lat, lon = coordenadas  # desempaquetado

# Las tuplas son inmutables
# coordenadas[0] = 0  # TypeError

Usos típicos

# Retorno múltiple de funciones
def min_max(lista):
    return min(lista), max(lista)  # devuelve tupla

minimo, maximo = min_max([3, 1, 4, 1, 5, 9])
print(f"Min: {minimo}, Max: {maximo}")  # Min: 1, Max: 9

# Named tuples — como structs ligeros
from collections import namedtuple

Punto = namedtuple("Punto", ["x", "y"])
p = Punto(3, 4)
print(p.x, p.y)         # 3 4
print(p)                 # Punto(x=3, y=4)

3. Diccionarios

Un diccionario almacena pares clave: valor. Las claves deben ser inmutables (strings, números, tuplas) y son únicas. Desde Python 3.7+ mantienen el orden de inserción.

persona = {
    "nombre": "Julian",
    "edad":   25,
    "pais":   "Colombia",
}

# Acceso
print(persona["nombre"])               # Julian
print(persona.get("email"))            # None (sin excepción)
print(persona.get("email", "N/A"))     # N/A

# Modificar / agregar
persona["email"] = "[email protected]"
persona["edad"]  = 26

# Eliminar
del persona["pais"]
eliminado = persona.pop("edad")        # elimina y devuelve

# Verificar
print("nombre" in persona)             # True
print(len(persona))                    # 2

Iterar diccionarios

notas = {"Matemáticas": 9.0, "Historia": 7.5, "Python": 10.0}

# Claves
for materia in notas:
    print(materia)

# Valores
for nota in notas.values():
    print(nota)

# Clave y valor
for materia, nota in notas.items():
    print(f"{materia}: {nota}")

Métodos útiles

config = {"debug": False, "max_conexiones": 10}
defaults = {"debug": True, "timeout": 30, "max_conexiones": 5}

# update — combina, el segundo sobreescribe el primero
config.update(defaults)
print(config)
# {"debug": True, "max_conexiones": 5, "timeout": 30}

# Fusión de dicts (Python 3.9+)
resultado = config | {"puerto": 8080}

# setdefault — agrega solo si la clave no existe
config.setdefault("version", "1.0")

Contador de frecuencias

texto = "el gato y el perro y el pato"
palabras = texto.split()

conteo = {}
for palabra in palabras:
    conteo[palabra] = conteo.get(palabra, 0) + 1

print(conteo)
# {'el': 3, 'gato': 1, 'y': 2, 'perro': 1, 'pato': 1}

# Con Counter de collections (más idiomático)
from collections import Counter
print(Counter(palabras))

Ejercicio 2

Dada una lista de productos [{"nombre": "Laptop", "precio": 1200, "categoria": "Electrónica"}, ...], escribe funciones para:

  • Agrupar productos por categoría devolviendo un dict[str, list]
  • Encontrar el producto más caro de cada categoría
  • Calcular el precio total del inventario

4. Conjuntos (Sets)

Un conjunto es una colección de elementos únicos sin orden definido. Ideal para eliminar duplicados y operaciones matemáticas de conjuntos.

a = {1, 2, 3, 4}
b = {3, 4, 5, 6}

# Crear desde lista (elimina duplicados)
unico = set([1, 2, 2, 3, 3, 3])
print(unico)  # {1, 2, 3}

# Operaciones
print(a | b)   # {1,2,3,4,5,6} — unión
print(a & b)   # {3,4}          — intersección
print(a - b)   # {1,2}          — diferencia (en a pero no en b)
print(a ^ b)   # {1,2,5,6}      — diferencia simétrica

# Métodos
a.add(5)
a.discard(99)  # elimina si existe, sin error si no existe
print(3 in a)  # True — muy rápido (O(1))

Eliminar duplicados preservando orden

lista = [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5]
sin_dup = list(dict.fromkeys(lista))  # preserva orden
print(sin_dup)  # [3, 1, 4, 5, 9, 2, 6]

5. Comprehensions

Las comprehensions son la forma idiomática de crear colecciones a partir de otras, en una sola expresión.

List comprehension

# Forma larga
cuadrados = []
for x in range(1, 11):
    cuadrados.append(x ** 2)

# List comprehension equivalente
cuadrados = [x ** 2 for x in range(1, 11)]
print(cuadrados)  # [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

# Con filtro
pares = [x for x in range(20) if x % 2 == 0]
print(pares)  # [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]

# Transformar strings
palabras = ["hola", "mundo", "python"]
mayusculas = [p.upper() for p in palabras]
print(mayusculas)  # ['HOLA', 'MUNDO', 'PYTHON']

# Anidada
matriz = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
plana = [elem for fila in matriz for elem in fila]
print(plana)  # [1, 2, 3, 4, 5, 6, 7, 8, 9]

Dict comprehension

nombres = ["Ana", "Bob", "Carlos"]
longitudes = {nombre: len(nombre) for nombre in nombres}
print(longitudes)  # {'Ana': 3, 'Bob': 3, 'Carlos': 6}

# Invertir diccionario
original  = {"a": 1, "b": 2, "c": 3}
invertido = {v: k for k, v in original.items()}
print(invertido)  # {1: 'a', 2: 'b', 3: 'c'}

# Filtrar diccionario
precios = {"Laptop": 1200, "Mouse": 25, "Teclado": 80, "Monitor": 400}
caros = {k: v for k, v in precios.items() if v > 100}
print(caros)  # {'Laptop': 1200, 'Monitor': 400}

Set comprehension

numeros = [1, 2, 2, 3, 4, 4, 5]
unicos_pares = {x for x in numeros if x % 2 == 0}
print(unicos_pares)  # {2, 4}

Expresiones generadoras

Son como list comprehensions pero sin crear la lista en memoria — evalúan elemento a elemento. Ideales para grandes volúmenes de datos.

# List comprehension — crea TODA la lista en memoria
suma_lc = sum([x ** 2 for x in range(1_000_000)])

# Generadora — calcula uno a uno sin almacenar
suma_gen = sum(x ** 2 for x in range(1_000_000))  # nota: sin corchetes

# Mismo resultado, mucho menos memoria
print(suma_gen)  # 333332833333500000
# Generador con función
def fibonacci():
    a, b = 0, 1
    while True:
        yield a
        a, b = b, a + b

gen = fibonacci()
primeros_10 = [next(gen) for _ in range(10)]
print(primeros_10)  # [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]

Ejercicio 3

Dado el siguiente dataset de ventas:

ventas = [
    {"producto": "Laptop",  "precio": 1200, "unidades": 5},
    {"producto": "Mouse",   "precio": 25,   "unidades": 50},
    {"producto": "Teclado", "precio": 80,   "unidades": 30},
    {"producto": "Monitor", "precio": 400,  "unidades": 10},
]

Usando comprehensions (sin bucles for explícitos):

  1. Lista de productos cuya facturación (precio × unidades) supera 1000
  2. Diccionario {producto: facturación}
  3. Total facturado usando expresión generadora

6. Errores Comunes

Error 1 — Modificar una lista mientras la iteras

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

# Incorrecto: modifica la lista durante la iteración
for n in numeros:
    if n % 2 == 0:
        numeros.remove(n)  # se saltan elementos
print(numeros)  # [1, 3, 5] — parece correcto, pero con [1,2,3,4,5,6] falla

# Crea una nueva lista con comprehension
numeros = [n for n in numeros if n % 2 != 0]

Error 2 — Copia superficial de listas anidadas

original = [[1, 2], [3, 4]]
copia = original.copy()  # copia superficial

copia[0].append(99)
print(original)  # [[1, 2, 99], [3, 4]] — ¡la original también cambió!

# Copia profunda
import copy
copia = copy.deepcopy(original)
copia[0].append(99)
print(original)  # [[1, 2], [3, 4]] — sin cambios

Error 3 — Usar lista cuando necesitas conjunto

# Verificar pertenencia en lista es O(n)
usuarios_vip = ["julian", "ana", "carlos"]  # lista con 10.000 elementos → lento
if "julian" in usuarios_vip:  # recorre hasta encontrar
    print("VIP")

# Conjunto: O(1) sin importar el tamaño
usuarios_vip = {"julian", "ana", "carlos"}
if "julian" in usuarios_vip:  # inmediato
    print("VIP")

Resumen

Colección Mutable Ordenada Duplicados Acceso por clave
list Índice numérico
tuple No Índice numérico
dict Sí (3.7+) Claves únicas Clave
set No No

Próximos pasos

  • POO en Python: clases, herencia, métodos especiales, dataclasses
  • Módulos útiles: itertools, functools, collections (Counter, defaultdict, deque)
  • Pandas: la librería de análisis de datos construida sobre estas colecciones