collections.UserDict es una clase auxiliar para crear diccionarios personalizados mediante composición. En lugar de depender directamente de los detalles internos de dict, guarda los valores en un diccionario normal expuesto como data y dirige las operaciones por métodos extensibles.
Este diseño facilita validación de claves, normalización de valores, logging, control de acceso y APIs de dominio coherentes.
Ejemplo básico
from collections import UserDict
class ClavesTexto(UserDict):
def __setitem__(self, clave, valor):
if not isinstance(clave, str):
raise TypeError("la clave debe ser texto")
super().__setitem__(clave, valor)
La validación queda centralizada y operaciones como update están diseñadas para respetar el comportamiento personalizado.
El atributo data
config = ClavesTexto({"modo": "producción"})
print(config.data)
data contiene el diccionario real. Modificarlo directamente puede saltarse reglas implementadas en métodos públicos.
Normalizar claves
class DiccionarioCasefold(UserDict):
def __setitem__(self, clave, valor):
super().__setitem__(str(clave).casefold(), valor)
def __getitem__(self, clave):
return super().__getitem__(str(clave).casefold())
def __contains__(self, clave):
return super().__contains__(str(clave).casefold())
Aplica la misma normalización en lectura, escritura, borrado y comprobación de presencia.
Validar valores
class Puntuaciones(UserDict):
def __setitem__(self, jugador, puntos):
puntos = int(puntos)
if puntos < 0:
raise ValueError("puntuación negativa")
super().__setitem__(jugador, puntos)
Documenta las conversiones permitidas y evita ocultar entradas inválidas.
Usar __missing__
class Contadores(UserDict):
def __missing__(self, clave):
return 0
__missing__ se aplica al acceso con corchetes, no necesariamente a get o membership. Usa defaultdict cuando quieras inserción automática.
UserDict frente a heredar de dict
Una subclase directa de dict puede ser más rápida y útil cuando una API exige el tipo concreto. UserDict ofrece una superficie de extensión más simple y predecible.
UserDict frente a MutableMapping
Implementa MutableMapping cuando los datos viven en una base de datos, cache remoto u otra estructura. Elige UserDict cuando un diccionario interno sea suficiente.
Copias y atributos adicionales
Prueba copy, deepcopy y reconstrucción cuando la clase guarda metadatos además de data.
class Config(UserDict):
def __init__(self, *args, origen=None, **kwargs):
self.origen = origen
super().__init__(*args, **kwargs)
Serialización
Algunas bibliotecas JSON esperan un diccionario concreto. Convierte explícitamente:
import json
json.dumps(dict(config), ensure_ascii=False)
Errores comunes
- Modificar
datadirectamente. - Normalizar solo en
__setitem__. - Ignorar métodos de borrado y actualización.
- Suponer que toda biblioteca acepta cualquier Mapping.
- Añadir efectos secundarios sorprendentes.
Buenas prácticas
Mantén invariantes pequeñas, usa super(), prueba todos los caminos de mutación y expone métodos de dominio cuando las reglas sean complejas. Consulta las guías internas de diccionarios y collections.
Conclusión
UserDict es una base práctica para mappings personalizados respaldados por un diccionario común. Favorece composición y reglas previsibles.







