Diccionarios
Los diccionarios mapean claves hasheables a valores arbitrarios con una búsqueda promedio de O(1). Son la herramienta predeterminada para registros, índices, cachés y tablas de despacho en el código de aplicación de Python.
Receta
defaults = {"retries": 3, "timeout": 30}
overrides = {"timeout": 60}
config = defaults | overrides
for key in config:
print(key, config[key])
if "retries" not in config:
config["retries"] = 1Cuándo usar esto:
- Registros tipo JSON y cargas útiles de API
- Contar y agrupar (a menudo con
Counter) - Cachés de memorización indexadas por argumentos
- Tablas de despacho de cadenas a manejadores
Ejemplo de Trabajo
from collections.abc import Callable
Handler = Callable[[dict], str]
def dispatch(handlers: dict[str, Handler], event: dict) -> str:
kind = str(event.get("type", "unknown"))
handler = handlers.get(kind, handlers["unknown"])
return handler(event)
def merge_records(base: dict[str, object], patch: dict[str, object]) -> dict[str, object]:
merged = base.copy()
merged.update(patch)
return merged
def invert_unique(mapping: dict[str, int]) -> dict[int, str]:
return {value: key for key, value in mapping.items()}
if __name__ == "__main__":
handlers: dict[str, Handler] = {
"user.created": lambda e: f"create {e['id']}",
"unknown": lambda e: "noop",
}
print(dispatch(handlers, {"type": "user.created", "id": 42}))
print(merge_records({"a": 1}, {"b": 2}))Lo que esto demuestra:
handlers.get(kind, default)evitaKeyErrorpara eventos desconocidosdict.copy+updatefusiona registros superficialmente- La comprensión de diccionario invierte el mapeo cuando los valores son únicos
- Los valores
Callableconvierten los diccionarios en tablas de despacho
Inmersión Profunda
Cómo Funciona
- Tabla hash - Las claves se hashean en cubetas; el direccionamiento abierto resuelve colisiones.
- Orden de inserción - El orden de iteración coincide con el orden de inserción (la reinserción mueve la clave al final en CPython 3.7+ solo para inserciones nuevas).
- Vistas -
keys(),values(),items()son vistas dinámicas, no instantáneas. - Igualdad - Dos diccionarios son iguales si tienen los mismos pares clave-valor independientemente del orden.
- fromkeys -
dict.fromkeys(keys, default)crea un diccionario con precaución por el valor predeterminado compartido.
Opciones de Fusión
| Sintaxis | ¿Muta la izquierda? |
|---|---|
a | b | No - nuevo dict (3.9+) |
a.update(b) | Sí |
{**a, **b} | No - nuevo dict |
Notas de Python
# setdefault solo cuando falta
counts: dict[str, int] = {}
counts.setdefault("a", 0)
counts["a"] += 1
# pop con valor predeterminado
value = config.pop("missing", None)Trampas
- Valores mutables compartidos a través de fromkeys -
dict.fromkeys(keys, [])comparte una lista. Solución: Comprensión con un objeto mutable nuevo. - Iterar claves y luego eliminar -
RuntimeErrorsi el tamaño cambia durante la iteración. Solución: Usarlist(d)para crear una instantánea primero. - Usar float NaN como clave - NaN != NaN rompe las suposiciones de unicidad. Solución: Evitar o normalizar.
- Memoria de dict grande - Se almacena cada objeto clave. Solución: Considerar una base de datos, un índice en disco o objetos
__slots__para registros. - Confiar en el orden para pruebas de igualdad - El orden difiere entre construcciones. Solución: Comparar como diccionarios, no como listas de claves.
Alternativas
| Alternativa | Usar Cuando | No Usar Cuando |
|---|---|---|
TypedDict | Forma estática para diccionarios JSON | Se necesitan métodos o validación |
dataclass | Objetos estructurados con comportamiento | Se necesita un diccionario JSON literal |
Modelo Pydantic | Modelos de API validados | Bucle interno rápido |
sqlite | Índice persistente consultable | Mapa pequeño en memoria |
Preguntas Frecuentes
¿Están ordenados los claves de los dict?
Sí, el orden de inserción está garantizado. Reasignar una clave existente no cambia su posición en CPython 3.7+ (comportamiento de inserción nueva solamente).
¿Qué hace que una clave sea hasheable?
Tipos inmutables con __hash__ estable: str, int, tuplas de elementos hasheables. Los objetos mutables fallan.
¿`|` vs `update`?
| devuelve un nuevo diccionario fusionado. update muta en el lugar; elige según las necesidades de inmutabilidad.
¿Cómo uso `defaultdict`?
collections.defaultdict o setdefault; defaultdict es más limpio para patrones de agrupación.
¿Puedo ordenar los elementos de un dict?
sorted(d.items(), key=lambda kv: kv[1]) devuelve una lista de pares; el diccionario en sí se mantiene conceptualmente desordenado pero conserva el orden de inserción del diccionario reasignado.
¿Qué es `ChainMap`?
Busca en una pila de diccionarios sin copiar; útil para superposiciones de configuración con ámbito.
¿Cómo hacer una copia profunda de un dict?
copy.deepcopy cuando los mutables anidados deben ser independientes.
¿`get` vs `[]`?
d[k] lanza KeyError cuando falta. get devuelve None o un valor predeterminado; más seguro para claves opcionales.
¿Comprensión de dict vs bucle?
{k: f(v) for k, v in items} es idiomático para transformaciones con un filtro if opcional.
¿Cuándo no usar un dict?
Cuando necesitas análisis de columnas (pandas/polars) o uniones relacionales en muchas filas.
Relacionado
- Sets y Frozensets - operaciones de unicidad complementarias
- Módulo
collections- defaultdict, Counter - Inmutabilidad y Hashabilidad - claves válidas
- TypedDict y NamedTuple - registros tipados
Versiones de la pila: Esta página fue escrita para Python 3.14.0 (estable 3.14, mantenimiento 3.13), FastAPI 0.115+, Django 5.2, Flask 3.1, Pydantic 2, PyTorch 2.6+, pandas 2.2+, Polars 1.x, ruff 0.9+, y uv 0.6+.