ChainMap

 ChainMap es como una "cadena de diccionarios" que te permite trabajar con varios diccionarios como si fueran uno solo.

python
from collections import ChainMap

# Tenemos dos diccionarios
dic1 = {'a': 1, 'b': 2}
dic2 = {'c': 3, 'd': 4}

# Creamos un ChainMap
cadena = ChainMap(dic1, dic2)

print(cadena)  # ChainMap({'a': 1, 'b': 2}, {'c': 3, 'd': 4})

¿Cómo funciona?

ChainMap busca en orden: primero en el primer diccionario, luego en el segundo, y así sucesivamente.

python
# Accediendo a valores
print(cadena['a'])  # 1 (está en el primer diccionario)
print(cadena['c'])  # 3 (está en el segundo diccionario)

Ejemplo práctico: Configuraciones

python
from collections import ChainMap

# Configuración por defecto
config_default = {'color': 'azul', 'tamaño': 'mediano'}

# Configuración del usuario
config_usuario = {'color': 'rojo', 'fuente': 'Arial'}

# Juntamos ambas configuraciones
config_final = ChainMap(config_usuario, config_default)

print(config_final['color'])   # 'rojo' (usa el del usuario)
print(config_final['tamaño'])  # 'mediano' (usa el por defecto)
print(config_final['fuente'])  # 'Arial' (solo está en usuario)

Operaciones básicas

python
# Ver todos los elementos
for clave, valor in cadena.items():
    print(f"{clave}: {valor}")

# Ver solo las claves
print(list(cadena.keys()))

# Ver solo los valores
print(list(cadena.values()))

# Verificar si existe una clave
print('a' in cadena)  # True
print('z' in cadena)  # False

Modificar valores

python
# Las modificaciones afectan SOLO al primer diccionario
cadena['a'] = 100  # Modifica el primer diccionario
cadena['nuevo'] = 999  # Agrega al primer diccionario

print(dic1)  # {'a': 100, 'b': 2, 'nuevo': 999}
print(dic2)  # {'c': 3, 'd': 4} (sin cambios)

Métodos útiles

python
# Agregar un nuevo diccionario al principio
nuevo_dic = {'x': 10, 'y': 20}
cadena_nueva = cadena.new_child(nuevo_dic)

# Ver los diccionarios que forman la cadena
print(cadena.maps)  # [{'a': 100, 'b': 2, 'nuevo': 999}, {'c': 3, 'd': 4}]

# Ver los padres (todos menos el primero)
print(cadena.parents)  # ChainMap({'c': 3, 'd': 4})

Caso de uso real: Variables de entorno

python
import os
from collections import ChainMap

# Configuración por defecto
config_default = {'host': 'localhost', 'puerto': 8080}

# Variables de entorno (simuladas)
variables_entorno = {'host': 'mi-servidor.com', 'DEBUG': 'True'}

# Prioridad: entorno > por defecto
config = ChainMap(variables_entorno, config_default)

print(f"Servidor: {config['host']}:{config['puerto']}")
# Si existe en entorno usa ese valor, sino usa el por defecto

Resumen

  • ChainMap une varios diccionarios en uno "virtual"

  • Busca en orden del primero al último

  • Las modificaciones solo afectan al primer diccionario

  • Es eficiente porque no copia datos, solo crea referencias

¡Es perfecto para jerarquías de configuración, herencia de valores, o cuando necesitas buscar en múltiples fuentes de datos!

Comentarios

Entradas populares de este blog

¿Qué es un Closure?

Calculadora de edad

Funciones en Python: con y sin paréntesis