defaultdict

 defaultdict es un diccionario especial que proporciona un valor por defecto para las claves que no existen, evitando el error KeyError.

Sintaxis básica

python
from collections import defaultdict

# Crear un defaultdict
dd = defaultdict(tipo_o_funcion_por_defecto)

Ejemplos prácticos

1. defaultdict con listas (muy común)

python
from collections import defaultdict

# Sin defaultdict
estudiantes = {}
# estudiantes['matemáticas'].append('Ana')  # ¡KeyError!

# Con defaultdict
estudiantes = defaultdict(list)
estudiantes['matemáticas'].append('Ana')  # ¡Funciona!
estudiantes['matemáticas'].append('Carlos')
estudiantes['historia'].append('María')

print(estudiantes)
# defaultdict(<class 'list'>, {'matemáticas': ['Ana', 'Carlos'], 'historia': ['María']})

2. defaultdict con enteros (para contar)

python
from collections import defaultdict

# Contar frecuencia de palabras
texto = "manzana naranja manzana pera naranja manzana"
palabras = texto.split()

contador = defaultdict(int)
for palabra in palabras:
    contador[palabra] += 1

print(contador)
# defaultdict(<class 'int'>, {'manzana': 3, 'naranja': 2, 'pera': 1})

3. defaultdict con conjuntos

python
from collections import defaultdict

# Agrupar números por longitud
numeros = ['uno', 'dos', 'tres', 'cuatro', 'cinco']

grupos = defaultdict(set)
for num in numeros:
    grupos[len(num)].add(num)

print(grupos)
# defaultdict(<class 'set'>, {3: {'uno', 'dos'}, 4: {'tres', 'cinco'}, 6: {'cuatro'}})

4. Con función personalizada

python
from collections import defaultdict

def valor_por_defecto():
    return "No encontrado"

dd = defaultdict(valor_por_defecto)
dd['nombre'] = 'Juan'

print(dd['nombre'])  # Juan
print(dd['edad'])    # No encontrado

Comparación con dict normal

python
# Con dict normal
diccionario_normal = {}
try:
    valor = diccionario_normal['clave_inexistente']
except KeyError:
    valor = 'valor_por_defecto'

# Con defaultdict
dd = defaultdict(lambda: 'valor_por_defecto')
valor = dd['clave_inexistente']  # Automáticamente 'valor_por_defecto'

Casos de uso comunes

1. Agrupación de elementos

python
from collections import defaultdict

personas = [
    ('Ana', 'Ingeniera'),
    ('Carlos', 'Doctor'),
    ('María', 'Ingeniera'),
    ('Juan', 'Profesor')
]

por_profesion = defaultdict(list)
for nombre, profesion in personas:
    por_profesion[profesion].append(nombre)

print(por_profesion)
# defaultdict(<class 'list'>, {'Ingeniera': ['Ana', 'María'], 'Doctor': ['Carlos'], 'Profesor': ['Juan']})

2. Árboles y estructuras anidadas

python
from collections import defaultdict

def arbol():
    return defaultdict(arbol)

# Crear un árbol infinitamente anidado
mi_arbol = arbol()
mi_arbol['nivel1']['nivel2']['nivel3'] = 'valor'

print(mi_arbol['nivel1']['nivel2']['nivel3'])  # valor

Ventajas de defaultdict

  • ✅ Evita KeyError automáticamente

  • ✅ Código más limpio y legible

  • ✅ Útil para agrupaciones y conteos

  • ✅ Mantiene todas las funcionalidades de un dict normal

Consideraciones

  • No es thread-safe para escrituras concurrentes

  • Ocupa más memoria que un dict normal

  • El valor por defecto se crea incluso si solo accedes a la clave

defaultdict es especialmente útil cuando trabajas con estructuras de datos que necesitan valores por defecto automáticos

Comentarios

Entradas populares de este blog

¿Qué es un Closure?

Calculadora de edad

Funciones en Python: con y sin paréntesis