En esta página
Diccionarios y conjuntos
Diccionarios en Python
Los diccionarios son colecciones de pares clave-valor no ordenadas por posición (pero sí por inserción desde Python 3.7+). Son la estructura de datos más eficiente para buscar valores por clave, con una complejidad promedio de O(1):
# Formas de crear diccionarios
vacío = {}
vacío2 = dict()
# Literal
persona = {
"nombre": "Elena Martínez",
"edad": 32,
"ciudad": "Buenos Aires",
"activa": True
}
# Constructor dict() con keyword arguments
config = dict(host="localhost", puerto=8080, debug=False)
# Desde una lista de tuplas (pares clave-valor)
claves = ["x", "y", "z"]
valores = [10, 20, 30]
coordenadas = dict(zip(claves, valores))
print(coordenadas) # {'x': 10, 'y': 20, 'z': 30}
# fromkeys() — crear con claves predefinidas y valor inicial
plantilla = dict.fromkeys(["nombre", "email", "telefono"], None)
print(plantilla) # {'nombre': None, 'email': None, 'telefono': None}Acceso a valores
producto = {
"id": "P001",
"nombre": "Laptop Pro",
"precio": 1299.99,
"categoría": "Electrónica",
"stock": 15
}
# Acceso directo (lanza KeyError si no existe)
print(producto["nombre"]) # Laptop Pro
print(producto["precio"]) # 1299.99
# Acceso seguro con get()
print(producto.get("stock")) # 15
print(producto.get("descuento")) # None — no lanza error
print(producto.get("descuento", 0)) # 0 — valor por defecto personalizado
# Verificar existencia
print("precio" in producto) # True
print("descuento" in producto) # False
print("id" not in producto) # False
# Acceso a diccionarios anidados
tienda = {
"productos": {
"P001": {"nombre": "Laptop", "precio": 1299.99},
"P002": {"nombre": "Mouse", "precio": 29.99}
},
"ubicación": "Madrid"
}
# Forma segura con .get() encadenado
precio_laptop = tienda.get("productos", {}).get("P001", {}).get("precio", 0)
print(precio_laptop) # 1299.99Métodos esenciales de diccionario
keys(), values(), items()
empleado = {
"nombre": "Roberto Silva",
"departamento": "Ingeniería",
"salario": 75000,
"antigüedad": 5
}
# keys() — devuelve una vista de las claves
claves = empleado.keys()
print(list(claves)) # ['nombre', 'departamento', 'salario', 'antigüedad']
# values() — devuelve una vista de los valores
valores = empleado.values()
print(list(valores)) # ['Roberto Silva', 'Ingeniería', 75000, 5]
# items() — devuelve pares (clave, valor) como tuplas
for clave, valor in empleado.items():
print(f"{clave:15}: {valor}")
# Las vistas son dinámicas — reflejan cambios al dict
empleado["bonus"] = 5000
print(list(claves)) # ['nombre', 'departamento', 'salario', 'antigüedad', 'bonus']update(), pop(), popitem()
inventario = {"manzanas": 50, "peras": 30, "uvas": 20}
# update() — actualiza con otro diccionario o iterable de pares
inventario.update({"peras": 45, "sandías": 10})
print(inventario) # {'manzanas': 50, 'peras': 45, 'uvas': 20, 'sandías': 10}
# Operador | (Python 3.9+) — fusión sin modificar los originales
a = {"x": 1, "y": 2}
b = {"y": 10, "z": 3}
c = a | b # Las claves de b sobrescriben las de a
print(c) # {'x': 1, 'y': 10, 'z': 3}
print(a) # {'x': 1, 'y': 2} — sin cambios
# Operador |= (Python 3.9+) — actualización in-place
a |= b
print(a) # {'x': 1, 'y': 10, 'z': 3}
# pop() — elimina y devuelve el valor de la clave
stock_uvas = inventario.pop("uvas")
print(stock_uvas) # 20
print(inventario) # sin 'uvas'
# pop() con valor por defecto (no lanza error si no existe)
inexistente = inventario.pop("plátanos", "No encontrado")
print(inexistente) # No encontrado
# popitem() — elimina y devuelve el último par (LIFO en Python 3.7+)
ultimo_par = inventario.popitem()
print(ultimo_par) # ('sandías', 10)
# setdefault() — establece valor si la clave no existe
inventario.setdefault("kiwis", 0)
print(inventario["kiwis"]) # 0
# Si la clave ya existe, setdefault() NO la modifica
inventario.setdefault("manzanas", 999)
print(inventario["manzanas"]) # 50 — sin cambiosPatrones comunes con diccionarios
Contar ocurrencias
palabras = ["el", "cielo", "el", "mar", "el", "viento", "mar"]
# Forma manual
conteo: dict[str, int] = {}
for palabra in palabras:
conteo[palabra] = conteo.get(palabra, 0) + 1
print(conteo) # {'el': 3, 'cielo': 1, 'mar': 2, 'viento': 1}
# Con Counter del módulo collections (más eficiente)
from collections import Counter
conteo_counter = Counter(palabras)
print(conteo_counter) # Counter({'el': 3, 'mar': 2, ...})
print(conteo_counter.most_common(2)) # [('el', 3), ('mar', 2)]Agrupar elementos
from collections import defaultdict
empleados = [
{"nombre": "Ana", "departamento": "Ing"},
{"nombre": "Bruno", "departamento": "Ventas"},
{"nombre": "Carmen", "departamento": "Ing"},
{"nombre": "Diego", "departamento": "Ventas"},
{"nombre": "Elena", "departamento": "Ing"},
]
# defaultdict evita verificar si la clave existe
por_depto: defaultdict[str, list[str]] = defaultdict(list)
for emp in empleados:
por_depto[emp["departamento"]].append(emp["nombre"])
print(dict(por_depto))
# {'Ing': ['Ana', 'Carmen', 'Elena'], 'Ventas': ['Bruno', 'Diego']}Conjuntos (sets)
Los conjuntos son colecciones no ordenadas de elementos únicos y hashables. Son perfectos para eliminar duplicados y hacer operaciones matemáticas de conjuntos:
# Crear sets
vacío = set() # ¡No uses {} para crear un set vacío! (eso crea un dict)
numeros = {1, 2, 3, 4, 5}
letras = {"a", "b", "c", "d"}
con_duplicados = {1, 2, 2, 3, 3, 3} # {1, 2, 3} — duplicados eliminados
# Crear desde otros iterables
desde_lista = set([1, 2, 2, 3, 4, 4]) # {1, 2, 3, 4}
desde_string = set("programación") # letras únicas
sin_duplicados = set(["Ana", "Bruno", "Ana", "Carmen"]) # {'Ana', 'Bruno', 'Carmen'}
print(sin_duplicados) # {'Ana', 'Bruno', 'Carmen'}Métodos de conjunto
colores = {"rojo", "verde", "azul"}
# add() — agrega un elemento (in-place)
colores.add("amarillo")
print(colores)
# remove() — elimina (lanza KeyError si no existe)
colores.remove("verde")
# discard() — elimina sin error si no existe
colores.discard("morado") # No lanza error
colores.discard("azul") # Lo elimina
# pop() — elimina y devuelve un elemento aleatorio
elemento = colores.pop()
print(elemento) # Algún elemento (orden no garantizado)
# clear() — vacía el set
temp = {1, 2, 3}
temp.clear()
print(temp) # set()
# Pertenencia — O(1), mucho más rápido que en listas
frutas = {"manzana", "pera", "uva", "naranja"}
print("pera" in frutas) # True
print("sandía" in frutas) # False
print("sandía" not in frutas) # TrueOperaciones matemáticas de conjuntos
python_devs = {"Ana", "Bruno", "Carmen", "Diego"}
js_devs = {"Bruno", "Elena", "Diego", "Felipe"}
rust_devs = {"Carmen", "Gabriel"}
# Unión (|) — todos los elementos de ambos conjuntos
todos = python_devs | js_devs
print(todos) # {'Ana', 'Bruno', 'Carmen', 'Diego', 'Elena', 'Felipe'}
# Intersección (&) — elementos en ambos conjuntos
ambos = python_devs & js_devs
print(ambos) # {'Bruno', 'Diego'}
# Diferencia (-) — en el primero pero no en el segundo
solo_python = python_devs - js_devs
print(solo_python) # {'Ana', 'Carmen'}
# Diferencia simétrica (^) — en uno o en otro, pero no en ambos
exclusivos = python_devs ^ js_devs
print(exclusivos) # {'Ana', 'Carmen', 'Elena', 'Felipe'}
# Subconjunto y superconjunto
a = {1, 2, 3}
b = {1, 2, 3, 4, 5}
print(a.issubset(b)) # True — a ⊆ b
print(b.issuperset(a)) # True — b ⊇ a
print(a <= b) # True — equivalente a issubset()
print(b >= a) # True — equivalente a issuperset()
print(a.isdisjoint(rust_devs)) # True — no tienen elementos en común...
# (depende de los nombres)
# Métodos alternativos (equivalentes a los operadores)
print(python_devs.union(js_devs))
print(python_devs.intersection(js_devs))
print(python_devs.difference(js_devs))
print(python_devs.symmetric_difference(js_devs))frozenset — conjuntos inmutables
# frozenset es la versión inmutable de set
# Se puede usar como clave de diccionario o elemento de otro set
permisos_lectura = frozenset({"leer", "descargar"})
permisos_escritura = frozenset({"leer", "escribir", "editar"})
# Hashable — puede ser clave de dict
mapa_permisos = {
permisos_lectura: "Solo lectura",
permisos_escritura: "Lectura y escritura"
}
print(mapa_permisos[permisos_lectura]) # Solo lectura¿Cuándo usar cada estructura?
| Estructura | Cuándo usarla |
|---|---|
list |
Colección ordenada, puede cambiar, permite duplicados |
tuple |
Colección ordenada, no cambia (inmutable), permite duplicados |
dict |
Acceso rápido por clave, pares clave-valor, sin duplicados en claves |
set |
Elementos únicos, operaciones matemáticas, pruebas de pertenencia rápida |
frozenset |
Set inmutable que necesita ser hashable |
Resumen
Los diccionarios son esenciales para búsquedas O(1) por clave y para representar datos estructurados. Los conjuntos son ideales para trabajar con colecciones únicas y hacer operaciones matemáticas de teoría de conjuntos. En la próxima lección aprenderemos las comprensiones y generadores, que transformarán la forma en que construyes estas estructuras de datos.
Inicia sesión para guardar tu progreso