Python

Python

Tutorial Python: Diccionarios

Aprende a usar diccionarios en Python con operaciones básicas, métodos y técnicas de iteración para manipular datos de forma eficiente.

Aprende Python y certifícate

Clave-valor

Los diccionarios en Python son estructuras de datos extremadamente versátiles que almacenan información en pares clave-valor. A diferencia de las listas o tuplas que organizan elementos por índices numéricos, los diccionarios permiten acceder a los datos mediante claves que nosotros definimos.

Imagina un diccionario como una agenda telefónica: para encontrar el número de teléfono de alguien (el valor), buscas por su nombre (la clave). Esta analogía ilustra perfectamente el concepto fundamental de los diccionarios en Python.

Estructura básica de un diccionario

Un diccionario se define utilizando llaves {} con pares clave-valor separados por dos puntos:

# Diccionario vacío
diccionario_vacio = {}

# Diccionario con datos
contactos = {
    "Ana": "612345678",
    "Carlos": "698765432",
    "Elena": "633333333"
}

En este ejemplo, los nombres ("Ana", "Carlos", "Elena") son las claves y los números telefónicos son los valores asociados a cada clave.

Características de las claves y valores

Las claves y valores en los diccionarios tienen características importantes que debes conocer:

  • Claves: Deben ser de tipos inmutables (strings, números, tuplas con elementos inmutables). Las listas o diccionarios no pueden ser claves.
  • Valores: Pueden ser de cualquier tipo de datos, incluyendo listas, diccionarios, objetos o funciones.
  • Unicidad: Cada clave debe ser única dentro del diccionario. Si intentas añadir una clave que ya existe, el valor anterior será sobrescrito.
# Las claves deben ser inmutables
diccionario_valido = {
    "nombre": "Juan",     # String como clave
    42: "respuesta",      # Número como clave
    (1, 2): "coordenada"  # Tupla como clave
}

# Esto causaría un error
# diccionario_invalido = {[1, 2]: "esto dará error"}  # Lista como clave

Creación de diccionarios

Existen varias formas de crear diccionarios en Python:

# Método 1: Usando llaves {}
estudiante = {"nombre": "Laura", "edad": 22, "carrera": "Informática"}

# Método 2: Usando dict()
colores = dict(rojo="#FF0000", verde="#00FF00", azul="#0000FF")

# Método 3: A partir de secuencias de pares
items = [("manzana", 0.85), ("naranja", 0.70), ("plátano", 0.60)]
precios = dict(items)

# Método 4: Usando dict comprehension (Python 3.x)
cuadrados = {x: x**2 for x in range(1, 6)}
# Resultado: {1: 1, 2: 4, 3: 9, 4: 16, 5: 25}

Acceso a valores

Para acceder a un valor, utilizamos su clave entre corchetes:

contactos = {"Ana": "612345678", "Carlos": "698765432"}

# Acceder al teléfono de Ana
telefono_ana = contactos["Ana"]
print(telefono_ana)  # Imprime: 612345678

Si intentas acceder a una clave que no existe, Python lanzará un error KeyError. Para evitarlo, puedes usar el método get() que devuelve un valor predeterminado (por defecto None) si la clave no existe:

# Acceso seguro con get()
telefono_elena = contactos.get("Elena")  # Devuelve None si no existe
print(telefono_elena)  # Imprime: None

# Podemos especificar un valor por defecto
telefono_elena = contactos.get("Elena", "No encontrado")
print(telefono_elena)  # Imprime: No encontrado

Verificación de existencia de claves

Para comprobar si una clave existe en un diccionario, podemos usar el operador in:

if "Ana" in contactos:
    print("Tenemos el teléfono de Ana")
else:
    print("No tenemos el teléfono de Ana")

Modificación de diccionarios

Los diccionarios son mutables, lo que significa que podemos modificar, añadir o eliminar pares clave-valor después de crearlos:

inventario = {"manzanas": 10, "naranjas": 5}

# Añadir un nuevo par clave-valor
inventario["plátanos"] = 8

# Modificar un valor existente
inventario["manzanas"] = 12

print(inventario)  # {'manzanas': 12, 'naranjas': 5, 'plátanos': 8}

Tipos de datos como valores

Los valores en un diccionario pueden ser de cualquier tipo, incluyendo listas, tuplas o incluso otros diccionarios:

# Diccionario con diferentes tipos de valores
usuario = {
    "nombre": "Miguel",
    "edad": 30,
    "activo": True,
    "hobbies": ["programación", "ajedrez", "senderismo"],
    "dirección": {
        "calle": "Calle Mayor 123",
        "ciudad": "Madrid",
        "código_postal": "28001"
    }
}

# Acceder a elementos anidados
ciudad = usuario["dirección"]["ciudad"]
print(ciudad)  # Madrid

# Acceder a elementos de una lista dentro del diccionario
primer_hobby = usuario["hobbies"][0]
print(primer_hobby)  # programación

Casos de uso prácticos

Los diccionarios son ideales para muchas situaciones cotidianas en programación:

# Configuración de una aplicación
config = {
    "modo_debug": True,
    "tema": "oscuro",
    "idioma": "es",
    "notificaciones": False
}

# Registro de datos de formulario
formulario = {
    "nombre": "Sara García",
    "email": "sara@ejemplo.com",
    "mensaje": "Me gustaría recibir más información sobre el curso."
}

# Conteo de frecuencias
texto = "hola mundo hola python mundo python python"
palabras = texto.split()
frecuencia = {}

for palabra in palabras:
    if palabra in frecuencia:
        frecuencia[palabra] += 1
    else:
        frecuencia[palabra] = 1

print(frecuencia)  # {'hola': 2, 'mundo': 2, 'python': 3}

Restricciones y consideraciones

Al trabajar con diccionarios, ten en cuenta estas consideraciones:

  • Hasta Python 3.6, los diccionarios no mantenían el orden de inserción. A partir de Python 3.7, el orden de inserción se preserva por defecto.
  • Las claves de diccionario deben ser hashables (tienen un valor hash que no cambia durante su vida útil).
  • Los diccionarios están optimizados para búsquedas rápidas por clave, con una complejidad de tiempo promedio O(1).
# En Python 3.7+ el orden se mantiene
versiones = {
    "Python": "3.11",
    "Java": "17",
    "JavaScript": "ES2022"
}

# Al iterar, se respeta el orden de inserción
for lenguaje, version in versiones.items():
    print(f"{lenguaje}: {version}")
# Imprime:
# Python: 3.11
# Java: 17
# JavaScript: ES2022

Los diccionarios son fundamentales en Python y constituyen una de las estructuras de datos más utilizadas por su flexibilidad y eficiencia. Dominar el concepto de pares clave-valor te permitirá organizar tus datos de manera más intuitiva y acceder a ellos de forma eficiente.

Operaciones básicas

Una vez que has creado un diccionario en Python, necesitarás realizar diversas operaciones para manipular sus datos. Los diccionarios ofrecen un conjunto de métodos integrados que facilitan estas tareas comunes.

Añadir y modificar elementos

Para añadir un nuevo par clave-valor a un diccionario o modificar un valor existente, simplemente asignamos el valor a la clave:

# Creamos un diccionario de calificaciones
calificaciones = {"Matemáticas": 85, "Historia": 72}

# Añadir una nueva asignatura
calificaciones["Ciencias"] = 90

# Modificar una calificación existente
calificaciones["Historia"] = 78

print(calificaciones)  # {'Matemáticas': 85, 'Historia': 78, 'Ciencias': 90}

También podemos usar el método update() para añadir o actualizar múltiples elementos a la vez:

# Actualizar varios elementos de una vez
calificaciones.update({"Inglés": 88, "Matemáticas": 87, "Arte": 95})

print(calificaciones)
# {'Matemáticas': 87, 'Historia': 78, 'Ciencias': 90, 'Inglés': 88, 'Arte': 95}

Eliminar elementos

Python ofrece varias formas de eliminar elementos de un diccionario:

  • 1. Usando del para eliminar un par clave-valor específico:
inventario = {"manzanas": 15, "naranjas": 8, "plátanos": 12}

# Eliminar las naranjas del inventario
del inventario["naranjas"]

print(inventario)  # {'manzanas': 15, 'plátanos': 12}
  • 2. Método pop() para eliminar y devolver el valor:
inventario = {"manzanas": 15, "naranjas": 8, "plátanos": 12}

# Eliminar y obtener el valor
cantidad_platanos = inventario.pop("plátanos")

print(f"Se eliminaron {cantidad_platanos} plátanos")  # Se eliminaron 12 plátanos
print(inventario)  # {'manzanas': 15, 'naranjas': 8}

El método pop() acepta un segundo parámetro opcional que especifica el valor a devolver si la clave no existe:

# Eliminar un elemento que podría no existir
cantidad_uvas = inventario.pop("uvas", 0)
print(f"Se eliminaron {cantidad_uvas} uvas")  # Se eliminaron 0 uvas
  • 3. Método popitem() para eliminar y devolver el último par insertado:
config = {"debug": True, "idioma": "es", "tema": "oscuro"}

# Eliminar el último elemento añadido (en Python 3.7+)
ultimo_elemento = config.popitem()

print(ultimo_elemento)  # ('tema', 'oscuro')
print(config)  # {'debug': True, 'idioma': 'es'}
  • 4. Método clear() para vaciar completamente el diccionario:
config = {"debug": True, "idioma": "es", "tema": "oscuro"}

# Vaciar el diccionario
config.clear()

print(config)  # {}

Copiar diccionarios

Es importante entender que asignar un diccionario a una nueva variable no crea una copia independiente:

original = {"a": 1, "b": 2}
referencia = original  # Esto no crea una copia, sino una referencia

referencia["c"] = 3
print(original)  # {'a': 1, 'b': 2, 'c': 3} - ¡El original también cambió!

Para crear una copia real, puedes usar los métodos copy() o dict():

# Método 1: Usando copy()
original = {"a": 1, "b": 2}
copia1 = original.copy()

# Método 2: Usando dict()
copia2 = dict(original)

# Modificar las copias no afecta al original
copia1["c"] = 3
copia2["d"] = 4

print(original)  # {'a': 1, 'b': 2}
print(copia1)    # {'a': 1, 'b': 2, 'c': 3}
print(copia2)    # {'a': 1, 'b': 2, 'd': 4}

Sin embargo, estas son copias superficiales. Si el diccionario contiene objetos anidados, estos seguirán siendo compartidos:

usuario = {
    "nombre": "Ana",
    "preferencias": {"tema": "claro", "notificaciones": True}
}

copia = usuario.copy()
copia["preferencias"]["tema"] = "oscuro"

# El cambio afecta también al original
print(usuario["preferencias"]["tema"])  # oscuro

Para crear una copia profunda, puedes usar el módulo copy:

import copy

usuario = {
    "nombre": "Ana",
    "preferencias": {"tema": "claro", "notificaciones": True}
}

# Copia profunda
copia_profunda = copy.deepcopy(usuario)
copia_profunda["preferencias"]["tema"] = "oscuro"

# El original no se ve afectado
print(usuario["preferencias"]["tema"])  # claro
print(copia_profunda["preferencias"]["tema"])  # oscuro

Obtener claves, valores e items

Los diccionarios proporcionan métodos para obtener vistas de sus claves, valores o pares clave-valor:

producto = {
    "nombre": "Portátil",
    "precio": 899,
    "stock": 15,
    "disponible": True
}

# Obtener todas las claves
claves = producto.keys()
print(claves)  # dict_keys(['nombre', 'precio', 'stock', 'disponible'])

# Obtener todos los valores
valores = producto.values()
print(valores)  # dict_values(['Portátil', 899, 15, True])

# Obtener todos los pares clave-valor
items = producto.items()
print(items)  # dict_items([('nombre', 'Portátil'), ('precio', 899), ('stock', 15), ('disponible', True)])

Estos métodos devuelven vistas dinámicas que se actualizan automáticamente cuando el diccionario cambia:

producto = {"nombre": "Portátil", "precio": 899}
claves = producto.keys()

print(claves)  # dict_keys(['nombre', 'precio'])

# Añadir un nuevo elemento
producto["marca"] = "TechBrand"

# La vista de claves se actualiza automáticamente
print(claves)  # dict_keys(['nombre', 'precio', 'marca'])

Para convertir estas vistas en listas, simplemente usamos la función list():

producto = {"nombre": "Portátil", "precio": 899, "stock": 15}

# Convertir a listas
lista_claves = list(producto.keys())
lista_valores = list(producto.values())

print(lista_claves)  # ['nombre', 'precio', 'stock']
print(lista_valores)  # ['Portátil', 899, 15]

Fusionar diccionarios

En Python 3.9+, puedes usar el operador | para combinar diccionarios:

# Python 3.9+
datos_personales = {"nombre": "Carlos", "edad": 28}
datos_contacto = {"email": "carlos@ejemplo.com", "teléfono": "612345678"}

# Fusionar con el operador |
usuario_completo = datos_personales | datos_contacto

print(usuario_completo)
# {'nombre': 'Carlos', 'edad': 28, 'email': 'carlos@ejemplo.com', 'teléfono': '612345678'}

En versiones anteriores, puedes usar update() o desempaquetado de diccionarios:

# Método 1: Con update() (modifica el primer diccionario)
datos_personales = {"nombre": "Carlos", "edad": 28}
datos_contacto = {"email": "carlos@ejemplo.com", "teléfono": "612345678"}

datos_combinados = datos_personales.copy()  # Crear copia para no modificar el original
datos_combinados.update(datos_contacto)

# Método 2: Con desempaquetado (Python 3.5+)
datos_combinados = {**datos_personales, **datos_contacto}

Si hay claves duplicadas, el valor del segundo diccionario sobrescribe al primero:

config_predeterminada = {"tema": "claro", "idioma": "es", "notificaciones": True}
config_usuario = {"tema": "oscuro", "autoguardado": True}

# La configuración del usuario tiene prioridad
config_final = config_predeterminada | config_usuario
print(config_final)
# {'tema': 'oscuro', 'idioma': 'es', 'notificaciones': True, 'autoguardado': True}

Métodos de búsqueda y recuperación

Además de get(), Python ofrece otros métodos útiles para trabajar con diccionarios:

  • setdefault(): Devuelve el valor de una clave, pero si la clave no existe, la añade con un valor predeterminado:
contador_palabras = {}
texto = "el perro persigue al gato y el gato corre"

for palabra in texto.split():
    # Si la palabra no existe, la añade con valor 0 y luego suma 1
    contador_palabras.setdefault(palabra, 0)
    contador_palabras[palabra] += 1

print(contador_palabras)
# {'el': 2, 'perro': 1, 'persigue': 1, 'al': 1, 'gato': 2, 'y': 1, 'corre': 1}

Este método es especialmente útil para inicializar valores:

# Sin setdefault
estudiantes_por_clase = {}
if "1A" not in estudiantes_por_clase:
    estudiantes_por_clase["1A"] = []
estudiantes_por_clase["1A"].append("Ana")

# Con setdefault (más conciso)
estudiantes_por_clase = {}
estudiantes_por_clase.setdefault("1A", []).append("Carlos")
  • fromkeys(): Crea un nuevo diccionario con las claves especificadas y un valor predeterminado:
# Crear un diccionario con valores predeterminados
materias = ["Matemáticas", "Historia", "Ciencias", "Literatura"]
calificaciones = dict.fromkeys(materias, 0)

print(calificaciones)
# {'Matemáticas': 0, 'Historia': 0, 'Ciencias': 0, 'Literatura': 0}

Si omites el segundo parámetro, el valor predeterminado será None:

asistencia = dict.fromkeys(["Lunes", "Martes", "Miércoles", "Jueves", "Viernes"])
print(asistencia)
# {'Lunes': None, 'Martes': None, 'Miércoles': None, 'Jueves': None, 'Viernes': None}

Ejemplo práctico: Contador de frecuencias mejorado

Combinando varias operaciones básicas, podemos crear soluciones elegantes para problemas comunes:

def contar_frecuencias(texto):
    """Cuenta la frecuencia de cada palabra en un texto."""
    # Convertir a minúsculas y eliminar puntuación básica
    for caracter in ".,;:!?()[]{}\"'":
        texto = texto.replace(caracter, " ")
    
    palabras = texto.lower().split()
    frecuencias = {}
    
    for palabra in palabras:
        # Incrementar contador o inicializar a 1 si no existe
        frecuencias[palabra] = frecuencias.get(palabra, 0) + 1
    
    return frecuencias

texto_ejemplo = "Python es genial. Python es potente. Python es Python."
resultado = contar_frecuencias(texto_ejemplo)

# Mostrar las palabras ordenadas por frecuencia
palabras_ordenadas = sorted(resultado.items(), key=lambda x: x[1], reverse=True)

for palabra, frecuencia in palabras_ordenadas:
    print(f"{palabra}: {frecuencia}")

Este ejemplo muestra cómo podemos combinar operaciones básicas de diccionarios para crear una herramienta útil de análisis de texto.

Rendimiento de las operaciones

Las operaciones básicas en diccionarios de Python son extremadamente eficientes. La búsqueda, inserción y eliminación tienen una complejidad de tiempo promedio de O(1), lo que significa que el tiempo de ejecución no aumenta significativamente con el tamaño del diccionario.

Esta eficiencia hace que los diccionarios sean ideales para:

  • Cachés y memorización
  • Búsquedas rápidas por clave
  • Conteo y agrupación de datos
  • Implementación de grafos y árboles
# Ejemplo de uso como caché
def fibonacci(n, cache={}):
    """Calcula el n-ésimo número de Fibonacci usando memorización."""
    if n in cache:
        return cache[n]
    
    if n <= 1:
        resultado = n
    else:
        resultado = fibonacci(n-1) + fibonacci(n-2)
    
    cache[n] = resultado
    return resultado

# Calcular fibonacci(100) sería extremadamente lento sin caché
print(fibonacci(100))  # 354224848179261915075

Dominar estas operaciones básicas te permitirá aprovechar al máximo el potencial de los diccionarios en Python, una de las estructuras de datos más versátiles y eficientes del lenguaje.

Iteración

Una de las operaciones más comunes al trabajar con diccionarios en Python es recorrer sus elementos para procesarlos. Python ofrece varias formas eficientes de iterar sobre diccionarios, permitiéndonos acceder a sus claves, valores o ambos simultáneamente.

Iteración básica sobre claves

La forma más sencilla de iterar sobre un diccionario es recorrer sus claves. Cuando usamos un diccionario directamente en un bucle for, Python itera sobre sus claves:

productos = {
    "laptop": 899,
    "teléfono": 649,
    "tablet": 349,
    "auriculares": 89
}

# Iteración sobre las claves
for producto in productos:
    print(producto)

# Salida:
# laptop
# teléfono
# tablet
# auriculares

Este método es equivalente a usar el método keys(), aunque la primera forma es más concisa:

# Iteración explícita sobre las claves
for producto in productos.keys():
    print(producto)

Iteración sobre valores

Si solo necesitas trabajar con los valores del diccionario, puedes usar el método values():

precios = {
    "laptop": 899,
    "teléfono": 649,
    "tablet": 349,
    "auriculares": 89
}

# Calcular el precio total del inventario
total = 0
for precio in precios.values():
    total += precio

print(f"Valor total del inventario: {total}€")  # Valor total del inventario: 1986€

Este enfoque es útil cuando no necesitas saber a qué clave corresponde cada valor.

Iteración sobre pares clave-valor

La forma más completa de iterar sobre un diccionario es usando el método items(), que devuelve pares de clave-valor:

inventario = {
    "manzanas": 25,
    "plátanos": 12,
    "naranjas": 18,
    "uvas": 30
}

# Iterar sobre pares clave-valor
for fruta, cantidad in inventario.items():
    print(f"Tenemos {cantidad} unidades de {fruta}")

# Salida:
# Tenemos 25 unidades de manzanas
# Tenemos 12 unidades de plátanos
# Tenemos 18 unidades de naranjas
# Tenemos 30 unidades de uvas

La técnica de desempaquetado (fruta, cantidad) hace que el código sea más legible y expresivo. Es especialmente útil cuando necesitas tanto la clave como el valor durante la iteración.

Iteración con enumeración

Si necesitas un contador mientras iteras, puedes combinar items() con la función enumerate():

estudiantes = {
    "Ana": 9.2,
    "Carlos": 7.8,
    "Elena": 8.5,
    "David": 6.9
}

# Enumerar estudiantes por calificación
print("Ranking de estudiantes:")
for i, (nombre, nota) in enumerate(estudiantes.items(), 1):
    print(f"{i}. {nombre}: {nota}")

# Salida:
# Ranking de estudiantes:
# 1. Ana: 9.2
# 2. Carlos: 7.8
# 3. Elena: 8.5
# 4. David: 6.9

El segundo parámetro de enumerate() (el 1 en este caso) indica el valor inicial del contador.

Iteración ordenada

Desde Python 3.7, los diccionarios mantienen el orden de inserción de sus elementos. Sin embargo, a veces necesitamos iterar en un orden específico:

calificaciones = {
    "Matemáticas": 85,
    "Historia": 72,
    "Ciencias": 90,
    "Literatura": 78
}

# Iterar por orden alfabético de asignaturas
for asignatura in sorted(calificaciones):
    print(f"{asignatura}: {calificaciones[asignatura]}")

# Salida:
# Ciencias: 90
# Historia: 72
# Literatura: 78
# Matemáticas: 85

También podemos ordenar por los valores:

# Iterar por calificación (de mayor a menor)
for asignatura in sorted(calificaciones, key=calificaciones.get, reverse=True):
    print(f"{asignatura}: {calificaciones[asignatura]}")

# Salida:
# Ciencias: 90
# Matemáticas: 85
# Literatura: 78
# Historia: 72

Para un control más detallado, podemos ordenar los items directamente:

# Ordenar por calificación y luego por nombre (si hay empate)
ordenados = sorted(
    calificaciones.items(),
    key=lambda x: (x[1], x[0]),  # Ordenar por valor y luego por clave
    reverse=True
)

for asignatura, nota in ordenados:
    print(f"{asignatura}: {nota}")

Comprensiones de diccionarios

Las comprensiones de diccionarios (dictionary comprehensions) son una forma concisa y elegante de crear nuevos diccionarios a partir de iterables:

numeros = [1, 2, 3, 4, 5]

# Crear un diccionario de cuadrados
cuadrados = {num: num**2 for num in numeros}
print(cuadrados)  # {1: 1, 2: 4, 3: 9, 4: 16, 5: 25}

También podemos transformar diccionarios existentes:

precios = {"laptop": 899, "teléfono": 649, "tablet": 349}

# Aplicar 10% de descuento a todos los productos
precios_rebajados = {producto: round(precio * 0.9, 2) for producto, precio in precios.items()}
print(precios_rebajados)  # {'laptop': 809.1, 'teléfono': 584.1, 'tablet': 314.1}

Las comprensiones pueden incluir condiciones para filtrar elementos:

ventas = {
    "Enero": 1200,
    "Febrero": 1500,
    "Marzo": 1100,
    "Abril": 1800,
    "Mayo": 2000,
    "Junio": 1700
}

# Filtrar meses con ventas superiores a 1500
meses_destacados = {mes: venta for mes, venta in ventas.items() if venta > 1500}
print(meses_destacados)  # {'Febrero': 1500, 'Abril': 1800, 'Mayo': 2000, 'Junio': 1700}

Patrones comunes de iteración

Filtrado de elementos

Podemos filtrar elementos de un diccionario durante la iteración:

productos = {
    "laptop": {"precio": 899, "stock": 10},
    "teléfono": {"precio": 649, "stock": 5},
    "tablet": {"precio": 349, "stock": 0},
    "auriculares": {"precio": 89, "stock": 8}
}

# Filtrar productos sin stock
productos_disponibles = {}
for nombre, datos in productos.items():
    if datos["stock"] > 0:
        productos_disponibles[nombre] = datos

print(productos_disponibles)
# {'laptop': {'precio': 899, 'stock': 10}, 'teléfono': {'precio': 649, 'stock': 5}, 'auriculares': {'precio': 89, 'stock': 8}}

El mismo resultado con comprensión de diccionarios:

productos_disponibles = {nombre: datos for nombre, datos in productos.items() if datos["stock"] > 0}

Transformación de datos

Podemos transformar los datos mientras iteramos:

temperaturas_celsius = {
    "Madrid": 30,
    "Barcelona": 28,
    "Sevilla": 35,
    "Bilbao": 22
}

# Convertir a Fahrenheit (F = C * 9/5 + 32)
temperaturas_fahrenheit = {}
for ciudad, temp_c in temperaturas_celsius.items():
    temp_f = temp_c * 9/5 + 32
    temperaturas_fahrenheit[ciudad] = round(temp_f, 1)

print(temperaturas_fahrenheit)
# {'Madrid': 86.0, 'Barcelona': 82.4, 'Sevilla': 95.0, 'Bilbao': 71.6}

Agrupación de datos

La iteración es útil para agrupar datos según ciertos criterios:

estudiantes = [
    {"nombre": "Ana", "curso": "Matemáticas", "nota": 9.2},
    {"nombre": "Carlos", "curso": "Historia", "nota": 7.8},
    {"nombre": "Elena", "curso": "Matemáticas", "nota": 8.5},
    {"nombre": "David", "curso": "Historia", "nota": 6.9},
    {"nombre": "Laura", "curso": "Matemáticas", "nota": 9.0}
]

# Agrupar estudiantes por curso
por_curso = {}
for estudiante in estudiantes:
    curso = estudiante["curso"]
    if curso not in por_curso:
        por_curso[curso] = []
    por_curso[curso].append(estudiante)

# Calcular nota media por curso
for curso, lista_estudiantes in por_curso.items():
    total = sum(e["nota"] for e in lista_estudiantes)
    media = total / len(lista_estudiantes)
    print(f"{curso}: {media:.1f}")

# Salida:
# Matemáticas: 8.9
# Historia: 7.4

Iteración segura durante modificaciones

Un aspecto importante a tener en cuenta es que no debes modificar un diccionario mientras lo estás iterando, ya que esto puede provocar comportamientos inesperados:

# Esto puede causar errores
diccionario = {"a": 1, "b": 2, "c": 3}
for clave in diccionario:
    if clave == "b":
        del diccionario[clave]  # ¡Error! Modificar durante la iteración

La solución es crear una copia de las claves antes de iterar:

# Forma segura
diccionario = {"a": 1, "b": 2, "c": 3}
for clave in list(diccionario.keys()):
    if clave == "b":
        del diccionario[clave]  # Ahora es seguro

print(diccionario)  # {'a': 1, 'c': 3}

Ejemplo práctico: Análisis de datos

Veamos un ejemplo más completo que combina varias técnicas de iteración para analizar datos:

ventas_por_region = {
    "Norte": {"Q1": 10000, "Q2": 12000, "Q3": 9500, "Q4": 11500},
    "Sur": {"Q1": 8500, "Q2": 9500, "Q3": 12000, "Q4": 13000},
    "Este": {"Q1": 9000, "Q2": 8000, "Q3": 7500, "Q4": 9500},
    "Oeste": {"Q1": 11000, "Q2": 10500, "Q3": 14000, "Q4": 15500}
}

# 1. Calcular ventas totales por región
ventas_totales = {}
for region, trimestres in ventas_por_region.items():
    total_region = sum(trimestres.values())
    ventas_totales[region] = total_region

# 2. Encontrar la región con mayores ventas
region_max = max(ventas_totales.items(), key=lambda x: x[1])
print(f"La región con mayores ventas es {region_max[0]} con {region_max[1]}€")

# 3. Calcular ventas por trimestre (todas las regiones)
ventas_por_trimestre = {"Q1": 0, "Q2": 0, "Q3": 0, "Q4": 0}
for region, trimestres in ventas_por_region.items():
    for trimestre, venta in trimestres.items():
        ventas_por_trimestre[trimestre] += venta

# 4. Mostrar resultados
print("\nVentas totales por región:")
for region, total in sorted(ventas_totales.items(), key=lambda x: x[1], reverse=True):
    print(f"{region}: {total}€")

print("\nVentas por trimestre:")
for trimestre, total in ventas_por_trimestre.items():
    print(f"{trimestre}: {total}€")

Este ejemplo muestra cómo la iteración sobre diccionarios nos permite realizar análisis complejos de datos de forma clara y estructurada.

Rendimiento en iteraciones

La iteración sobre diccionarios en Python es muy eficiente, pero hay algunas consideraciones de rendimiento:

  • Iterar sobre keys() es ligeramente más rápido que sobre items().
  • Para diccionarios grandes, evita convertir las vistas a listas a menos que sea necesario.
  • Las comprensiones de diccionarios suelen ser más rápidas que los bucles for equivalentes.
# Más eficiente para diccionarios grandes
for clave in diccionario:  # en lugar de list(diccionario.keys())
    # Procesar clave
    pass

Dominar las técnicas de iteración sobre diccionarios te permitirá escribir código más limpio, expresivo y eficiente para procesar y transformar datos estructurados en Python.

Aprende Python online

Otros ejercicios de programación de Python

Evalúa tus conocimientos de esta lección Diccionarios con nuestros retos de programación de tipo Test, Puzzle, Código y Proyecto con VSCode, guiados por IA.

Módulo math

Python
Puzzle

Reto herencia

Python
Código

Excepciones

Python
Test

Introducción a Python

Python
Test

Reto variables

Python
Código

Funciones Python

Python
Puzzle

Reto funciones

Python
Código

Módulo datetime

Python
Test

Reto acumulación

Python
Código

Reto estructuras condicionales

Python
Código

Polimorfismo

Python
Test

Módulo os

Python
Test

Reto métodos dunder

Python
Código

Diccionarios

Python
Puzzle

Reto clases y objetos

Python
Código

Reto operadores

Python
Código

Operadores

Python
Test

Estructuras de control

Python
Puzzle

Funciones lambda

Python
Test

Reto diccionarios

Python
Código

Reto función lambda

Python
Código

Encapsulación

Python
Puzzle

Reto coleciones

Python
Proyecto

Reto funciones auxiliares

Python
Código

Crear módulos y paquetes

Python
Puzzle

Módulo datetime

Python
Puzzle

Excepciones

Python
Puzzle

Operadores

Python
Puzzle

Diccionarios

Python
Test

Reto map, filter

Python
Código

Reto tuplas

Python
Código

Proyecto gestor de tareas CRUD

Python
Proyecto

Tuplas

Python
Puzzle

Variables

Python
Puzzle

Tipos de datos

Python
Puzzle

Conjuntos

Python
Test

Reto mixins

Python
Código

Módulo csv

Python
Test

Módulo json

Python
Test

Herencia

Python
Test

Análisis de datos de ventas con Pandas

Python
Proyecto

Reto fechas y tiempo

Python
Proyecto

Reto estructuras de iteración

Python
Código

Funciones

Python
Test

Reto comprehensions

Python
Código

Variables

Python
Test

Reto serialización

Python
Proyecto

Módulo csv

Python
Puzzle

Reto polimorfismo

Python
Código

Polimorfismo

Python
Puzzle

Clases y objetos

Python
Código

Reto encapsulación

Python
Código

Estructuras de control

Python
Test

Importar módulos y paquetes

Python
Test

Módulo math

Python
Test

Funciones lambda

Python
Puzzle

Reto excepciones

Python
Código

Listas

Python
Puzzle

Reto archivos

Python
Proyecto

Encapsulación

Python
Test

Reto conjuntos

Python
Código

Clases y objetos

Python
Test

Instalación de Python y creación de proyecto

Python
Test

Reto listas

Python
Código

Tipos de datos

Python
Test

Crear módulos y paquetes

Python
Test

Tuplas

Python
Test

Herencia

Python
Puzzle

Reto acceso a sistema

Python
Proyecto

Proyecto sintaxis calculadora

Python
Proyecto

Importar módulos y paquetes

Python
Puzzle

Clases y objetos

Python
Puzzle

Módulo os

Python
Puzzle

Listas

Python
Test

Conjuntos

Python
Puzzle

Reto tipos de datos

Python
Código

Reto matemáticas

Python
Proyecto

Módulo json

Python
Puzzle

Todas las lecciones de Python

Accede a todas las lecciones de Python y aprende con ejemplos prácticos de código y ejercicios de programación con IDE web sin instalar nada.

Introducción A Python

Python

Introducción

Instalación Y Creación De Proyecto

Python

Introducción

Tema 2: Tipos De Datos, Variables Y Operadores

Python

Introducción

Instalación De Python

Python

Introducción

Tipos De Datos

Python

Sintaxis

Variables

Python

Sintaxis

Operadores

Python

Sintaxis

Estructuras De Control

Python

Sintaxis

Funciones

Python

Sintaxis

Estructuras Control Iterativo

Python

Sintaxis

Estructuras Control Condicional

Python

Sintaxis

Testing Con Pytest

Python

Sintaxis

Listas

Python

Estructuras De Datos

Tuplas

Python

Estructuras De Datos

Diccionarios

Python

Estructuras De Datos

Conjuntos

Python

Estructuras De Datos

Comprehensions

Python

Estructuras De Datos

Clases Y Objetos

Python

Programación Orientada A Objetos

Excepciones

Python

Programación Orientada A Objetos

Encapsulación

Python

Programación Orientada A Objetos

Herencia

Python

Programación Orientada A Objetos

Polimorfismo

Python

Programación Orientada A Objetos

Mixins Y Herencia Múltiple

Python

Programación Orientada A Objetos

Métodos Especiales (Dunder Methods)

Python

Programación Orientada A Objetos

Composición De Clases

Python

Programación Orientada A Objetos

Funciones Lambda

Python

Programación Funcional

Aplicación Parcial

Python

Programación Funcional

Entrada Y Salida, Manejo De Archivos

Python

Programación Funcional

Decoradores

Python

Programación Funcional

Generadores

Python

Programación Funcional

Paradigma Funcional

Python

Programación Funcional

Composición De Funciones

Python

Programación Funcional

Funciones Orden Superior Map Y Filter

Python

Programación Funcional

Funciones Auxiliares

Python

Programación Funcional

Reducción Y Acumulación

Python

Programación Funcional

Archivos Comprimidos

Python

Entrada Y Salida Io

Entrada Y Salida Avanzada

Python

Entrada Y Salida Io

Archivos Temporales

Python

Entrada Y Salida Io

Contexto With

Python

Entrada Y Salida Io

Módulo Csv

Python

Biblioteca Estándar

Módulo Json

Python

Biblioteca Estándar

Módulo Datetime

Python

Biblioteca Estándar

Módulo Math

Python

Biblioteca Estándar

Módulo Os

Python

Biblioteca Estándar

Módulo Re

Python

Biblioteca Estándar

Módulo Random

Python

Biblioteca Estándar

Módulo Time

Python

Biblioteca Estándar

Módulo Collections

Python

Biblioteca Estándar

Módulo Sys

Python

Biblioteca Estándar

Módulo Statistics

Python

Biblioteca Estándar

Módulo Pickle

Python

Biblioteca Estándar

Módulo Pathlib

Python

Biblioteca Estándar

Importar Módulos Y Paquetes

Python

Paquetes Y Módulos

Crear Módulos Y Paquetes

Python

Paquetes Y Módulos

Entornos Virtuales (Virtualenv, Venv)

Python

Entorno Y Dependencias

Gestión De Dependencias (Pip, Requirements.txt)

Python

Entorno Y Dependencias

Python-dotenv Y Variables De Entorno

Python

Entorno Y Dependencias

Acceso A Datos Con Mysql, Pymongo Y Pandas

Python

Acceso A Bases De Datos

Acceso A Mongodb Con Pymongo

Python

Acceso A Bases De Datos

Acceso A Mysql Con Mysql Connector

Python

Acceso A Bases De Datos

Novedades Python 3.13

Python

Características Modernas

Operador Walrus

Python

Características Modernas

Pattern Matching

Python

Características Modernas

Instalación Beautiful Soup

Python

Web Scraping

Sintaxis General De Beautiful Soup

Python

Web Scraping

Tipos De Selectores

Python

Web Scraping

Web Scraping De Html

Python

Web Scraping

Web Scraping Para Ciencia De Datos

Python

Web Scraping

Autenticación Y Acceso A Recursos Protegidos

Python

Web Scraping

Combinación De Selenium Con Beautiful Soup

Python

Web Scraping

Accede GRATIS a Python y certifícate

En esta lección

Objetivos de aprendizaje de esta lección

  • Comprender la estructura y características fundamentales de los diccionarios en Python.
  • Aprender a crear, acceder y modificar diccionarios utilizando diferentes métodos.
  • Conocer las operaciones básicas para añadir, eliminar, copiar y fusionar diccionarios.
  • Dominar las técnicas de iteración sobre claves, valores y pares clave-valor, incluyendo comprensiones.
  • Aplicar diccionarios en casos prácticos y entender su eficiencia y limitaciones.