Diccionarios en Python — 12 trucos que casi nadie usa
Los diccionarios son probablemente la estructura de datos más útil de Python. Más que las listas. Y sin embargo, casi todo el mundo los usa con cuatro métodos contados (d["clave"], d.get(), d.keys(), for clave, valor in d.items()) y se pierde un montón de cosas que ya están en el lenguaje, gratis, listas para usar.
En esta entrada te enseño 12 trucos que mejoran de verdad tu código diario con diccionarios. Nada de tonterías de tutorial — patrones que vas a usar la próxima semana.
Si te encuentras escribiendo if clave in d: d[clave].append(...) cada dos por tres, esta entrada es para ti.
Contenido
- 1 1. dict.get() con valor por defecto
- 2 2. dict.setdefault() para inicializar listas anidadas
- 3 3. collections.defaultdict — la versión profesional del truco anterior
- 4 4. collections.Counter — contar cosas en una línea
- 5 5. Mergear dos diccionarios con | (Python 3.9+)
- 6 6. Dict comprehensions
- 7 7. Iterar clave + valor con .items()
- 8 8. Comprobar pertenencia con in (no con .keys())
- 9 9. Desempaquetar un dict en argumentos con **
- 10 10. Diccionarios mantienen el orden de inserción (Python 3.7+)
- 11 11. dict.pop() con valor por defecto
- 12 12. dict.fromkeys() — crear un dict desde una lista de claves
- 13 Errores típicos al usar diccionarios
- 14 Resumen — los 12 trucos en una mirada
- 15 Tu siguiente paso
1. dict.get() con valor por defecto
Antes de tocar nada, lo más básico bien hecho. Si necesitas leer una clave que podría no existir, no escribas:
if "edad" in usuario:
edad = usuario["edad"]
else:
edad = 0
Escribe:
edad = usuario.get("edad", 0)
Si la clave no existe, devuelve el segundo argumento (0). Sin error, sin if, una línea. Si lo omites, devuelve None.
💡 Ojo:
usuario["edad"]lanzaKeyError.usuario.get("edad")devuelveNone. Saber cuál usar te ahorra horas de bugs.
2. dict.setdefault() para inicializar listas anidadas
Patrón mil veces visto: agrupar elementos por categoría.
peliculas = [
("Inception", "scifi"),
("Heat", "thriller"),
("Arrival", "scifi"),
]
por_genero = {}
for titulo, genero in peliculas:
if genero not in por_genero:
por_genero[genero] = []
por_genero[genero].append(titulo)
Lo mismo con setdefault:
por_genero = {}
for titulo, genero in peliculas:
por_genero.setdefault(genero, []).append(titulo)
setdefault(clave, []).append(...): si la clave no existe la crea con [], devuelve la lista (nueva o existente), y le hace .append(). Limpio.
3. collections.defaultdict — la versión profesional del truco anterior
Cuando vas a hacer ese patrón muchas veces, defaultdict es aún más limpio:
from collections import defaultdict
por_genero = defaultdict(list)
for titulo, genero in peliculas:
por_genero[genero].append(titulo)
defaultdict(list) significa “si una clave no existe al accederla, créala con una lista vacía”. Y con defaultdict(int) puedes hacer contadores en una línea.
votos = ["sí", "no", "sí", "sí", "no"]
contador = defaultdict(int)
for v in votos:
contador[v] += 1
# defaultdict(<class 'int'>, {'sí': 3, 'no': 2})
Aunque para contar lo siguiente es aún mejor.
📥 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.
4. collections.Counter — contar cosas en una línea
Counter es una subclase de dict que cuenta elementos por ti:
from collections import Counter
palabras = ["python", "java", "python", "go", "python", "java"]
c = Counter(palabras)
# Counter({'python': 3, 'java': 2, 'go': 1})
print(c.most_common(2))
# [('python', 3), ('java', 2)]
Cuenta automático, ordenado por frecuencia con most_common(N). Útil para análisis rápidos: “¿qué palabra aparece más?”, “¿qué error es más frecuente?”, “¿qué usuario hace más peticiones?”.
5. Mergear dos diccionarios con | (Python 3.9+)
Si quieres combinar dos diccionarios:
defaults = {"tema": "oscuro", "idioma": "es", "fontsize": 14}
usuario = {"idioma": "en", "fontsize": 16}
config = defaults | usuario
# {"tema": "oscuro", "idioma": "en", "fontsize": 16}
Lo de la derecha gana en colisiones. Antes había que hacer {**defaults, **usuario}. Ahora con | queda más limpio.
⚡ Tip-friki:
defaults |= usuariomodificadefaultsin-place, equivalente adefaults.update(usuario). Útil cuando ya tienes un dict y quieres parchear sobre él.
6. Dict comprehensions
Igual que las list comprehensions pero para diccionarios:
# Diccionario de cuadrados
cuadrados = {n: n**2 for n in range(5)}
# {0: 0, 1: 1, 2: 4, 3: 9, 4: 16}
# Invertir un diccionario (claves ↔ valores)
original = {"a": 1, "b": 2, "c": 3}
invertido = {v: k for k, v in original.items()}
# {1: "a", 2: "b", 3: "c"}
# Filtrar entradas
edades = {"Ana": 30, "Luis": 17, "Marta": 22, "Pedro": 15}
mayores = {nombre: edad for nombre, edad in edades.items() if edad >= 18}
# {"Ana": 30, "Marta": 22}
💡 ¿Más patrones de comprehensions? Mira list comprehensions en Python.
7. Iterar clave + valor con .items()
Lo básico bien hecho. No hagas:
for clave in d:
print(clave, d[clave]) # ❌ accesos extra
Haz:
for clave, valor in d.items():
print(clave, valor) # ✓ una sola pasada
Más rápido y mucho más legible. Si solo necesitas claves, for k in d:. Si solo valores, for v in d.values():.
8. Comprobar pertenencia con in (no con .keys())
Algo que mucha gente sigue escribiendo mal:
if "Ana" in d.keys(): # ❌ funciona pero es redundante
...
if "Ana" in d: # ✓ exactamente lo mismo, más limpio
...
in sobre un dict comprueba claves por defecto. Si quieres comprobar valores, sí necesitas if "España" in d.values():.
9. Desempaquetar un dict en argumentos con **
Si tienes un dict y quieres pasar cada clave como argumento por nombre:
def crear_pelicula(titulo, año, genero):
print(f"{titulo} ({año}) — {genero}")
datos = {"titulo": "Inception", "año": 2010, "genero": "scifi"}
crear_pelicula(**datos)
# Inception (2010) — scifi
**datos desempaqueta el dict como si hubieras escrito titulo="Inception", año=2010, genero="scifi". Patrón muy útil cuando vienes con datos de JSON o de la BBDD.
💡 Para entenderlo a fondo:
*argsy**kwargsen Python.
10. Diccionarios mantienen el orden de inserción (Python 3.7+)
Antes los dicts no garantizaban orden. Ahora sí. El orden de inserción se mantiene:
ranking = {}
ranking["Ana"] = 95
ranking["Luis"] = 88
ranking["Marta"] = 91
for nombre, puntos in ranking.items():
print(nombre, puntos)
# Ana 95
# Luis 88
# Marta 91
Sirve para ordenar y mantener orden temporal de eventos. Si necesitas ordenar por valor:
top = dict(sorted(ranking.items(), key=lambda kv: kv[1], reverse=True))
# {"Ana": 95, "Marta": 91, "Luis": 88}
sorted(d.items(), key=lambda kv: kv[1]) ordena por valor. Con reverse=True, descendente.
11. dict.pop() con valor por defecto
Como get(), pero eliminando la clave del dict si existe:
config = {"tema": "oscuro", "idioma": "es", "deprecated_flag": True}
flag = config.pop("deprecated_flag", False)
# config ahora no tiene la clave 'deprecated_flag'
# flag = True
flag2 = config.pop("inexistente", False)
# flag2 = False, no lanza KeyError
Útil para “extraer y limpiar de paso”, típico al normalizar datos de entrada.
12. dict.fromkeys() — crear un dict desde una lista de claves
Cuando quieres inicializar un dict con muchas claves al mismo valor:
campos = ["nombre", "email", "telefono", "direccion"]
formulario = dict.fromkeys(campos, "")
# {"nombre": "", "email": "", "telefono": "", "direccion": ""}
contadores = dict.fromkeys(["A", "B", "C"], 0)
# {"A": 0, "B": 0, "C": 0}
⚠️ Ojo: si usas un valor mutable (lista, dict) como default, todas las claves comparten la misma referencia.
dict.fromkeys(["a", "b"], [])te da un dict donde mutar la lista de “a” muta también la de “b”. Para eso, usa una comprehension:{c: [] for c in claves}.
Errores típicos al usar diccionarios
# 1. Acceder con [] cuando podría no existir
nombre = usuario["nombre"] # ❌ KeyError si no existe
nombre = usuario.get("nombre", "Anónimo") # ✓
# 2. Modificar el dict mientras se itera
for clave in d:
if d[clave] is None:
del d[clave] # ❌ RuntimeError: dictionary changed size during iteration
# Forma correcta:
for clave in list(d): # itera una copia
if d[clave] is None:
del d[clave]
# o:
d = {k: v for k, v in d.items() if v is not None}
# 3. Confundir d.keys() con list(d.keys())
keys = d.keys() # vista dinámica del dict; cambia si el dict cambia
keys = list(d.keys()) # snapshot, no cambia con el dict
# 4. Usar listas como claves de dict
d = {[1, 2]: "algo"} # ❌ TypeError: las listas no son hashables
d = {(1, 2): "algo"} # ✓ tuplas sí lo son
Resumen — los 12 trucos en una mirada
| # | Truco | Para qué |
|---|---|---|
| 1 | d.get(k, default) |
Leer con valor por defecto sin KeyError |
| 2 | d.setdefault(k, []).append(x) |
Inicializar y añadir en una línea |
| 3 | defaultdict(list) |
Mismo patrón, aún más limpio cuando se repite |
| 4 | Counter(iterable) |
Contar frecuencias en una línea |
| 5 | d1 \| d2 |
Mergear dos dicts (Python 3.9+) |
| 6 | {k: v for ... in ...} |
Dict comprehensions |
| 7 | for k, v in d.items(): |
Iterar clave-valor en una pasada |
| 8 | if k in d: |
Comprobar pertenencia (no .keys()) |
| 9 | funcion(**dict) |
Desempaquetar dict como argumentos |
| 10 | Orden de inserción garantizado | Útil para ordenar y para sorted() |
| 11 | d.pop(k, default) |
Extraer y eliminar con default |
| 12 | dict.fromkeys(claves, valor) |
Inicializar muchas claves a la vez |
¿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 tienes herramientas para escribir código mucho más limpio con diccionarios. La próxima vez que veas un if clave in d: con tres líneas para inicializar una lista — recuerda setdefault o defaultdict. La próxima vez que cuentes a mano — recuerda Counter.
Si quieres aprender estructuras de datos, funciones, clases y proyectos reales con Python desde la base, en El Pythonista lo enseño paso a paso.
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, 35+ lecciones, código revisado, ejercicios y un proyecto real (MovieTracker) que crece contigo desde la primera variable hasta el deploy a producción.
35+ lecciones · Proyecto real · Acceso de por vida · 14 días de garantía
