Ir al contenido principal

Diccionarios: pares clave-valor

Introducción

Los diccionarios son una de las estructuras de datos más versátiles y útiles en Python. A diferencia de las listas y tuplas, que almacenan elementos en secuencia ordenada accesibles por índices numéricos, los diccionarios nos permiten organizar datos mediante pares de clave-valor. Esta estructura facilita enormemente la búsqueda y recuperación de información específica cuando conocemos su identificador o clave. Los diccionarios son fundamentales para el manejo eficiente de datos en Python y encontraremos su uso en prácticamente cualquier programa que maneje conjuntos complejos de información.

Definición y creación de diccionarios

Un diccionario en Python es una colección desordenada (aunque desde Python 3.7 mantienen el orden de inserción) de pares clave-valor, donde cada clave debe ser única e inmutable. Las claves actúan como identificadores para acceder a los valores almacenados.

Hay varias formas de crear un diccionario:

# Método 1: Usando llaves {} con pares clave-valor
estudiante = {
    "nombre": "Laura",
    "apellido": "Sánchez",
    "edad": 22,
    "asignaturas": ["Matemáticas", "Física", "Programación"]
}
print(estudiante)

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

# Método 3: A partir de secuencias de pares
ciudades = dict([("Madrid", "España"), ("París", "Francia"), ("Roma", "Italia")])
print(ciudades)

# Método 4: Diccionario vacío
mi_diccionario = {}
print(type(mi_diccionario))  # Salida: <class 'dict'>

Acceso a los valores

Para acceder a un valor en un diccionario, utilizamos su clave correspondiente:

usuario = {
    "id": 1234,
    "nombre": "Carlos",
    "email": "carlos@ejemplo.com",
    "activo": True
}

# Acceso básico
print(usuario["nombre"])  # Salida: Carlos
print(usuario["email"])   # Salida: carlos@ejemplo.com

# Si intentamos acceder a una clave que no existe, obtendremos un error KeyError
try:
    print(usuario["telefono"])
except KeyError as e:
    print(f"Error: {e}")  # Salida: Error: 'telefono'

# Método get() - permite proporcionar un valor predeterminado si la clave no existe
print(usuario.get("email", "No disponible"))     # Salida: carlos@ejemplo.com
print(usuario.get("telefono", "No disponible"))  # Salida: No disponible

Modificación de diccionarios

Los diccionarios son estructuras mutables, lo que significa que podemos añadir, modificar o eliminar elementos:

producto = {
    "nombre": "Portátil",
    "precio": 799.99,
    "disponible": True
}

# Modificar un valor existente
producto["precio"] = 749.99
print(producto)  # El precio ha sido actualizado

# Añadir un nuevo par clave-valor
producto["marca"] = "TechPro"
print(producto)  # Ahora incluye la marca

# Eliminar un par clave-valor con del
del producto["disponible"]
print(producto)  # Ya no incluye 'disponible'

# Eliminar un par con pop() (devuelve el valor eliminado)
marca = producto.pop("marca")
print(f"Marca eliminada: {marca}")
print(producto)  # Ya no incluye 'marca'

# Eliminar y obtener el último par insertado con popitem() (desde Python 3.7)
ultimo_par = producto.popitem()
print(f"Último par eliminado: {ultimo_par}")
print(producto)

# Vaciar el diccionario
producto.clear()
print(producto)  # Salida: {}

Métodos comunes de diccionarios

Python proporciona varios métodos útiles para trabajar con diccionarios:

inventario = {
    "mesa": 15,
    "silla": 45,
    "lámpara": 20,
    "estantería": 8
}

# keys() - Devuelve un objeto vista con todas las claves
print(list(inventario.keys()))  # Convertimos a lista para imprimir

# values() - Devuelve un objeto vista con todos los valores
print(list(inventario.values()))

# items() - Devuelve un objeto vista con todos los pares clave-valor como tuplas
print(list(inventario.items()))

# update() - Actualiza un diccionario con los pares de otro
nuevos_items = {"sofá": 5, "mesa": 20}  # 'mesa' se actualizará
inventario.update(nuevos_items)
print(inventario)

# setdefault() - Inserta un par clave-valor si la clave no existe
inventario.setdefault("alfombra", 12)  # Se añade porque no existe
inventario.setdefault("silla", 50)     # No se modifica porque ya existe
print(inventario)

# fromkeys() - Crea un nuevo diccionario con las claves especificadas y el mismo valor
productos = ["laptop", "tablet", "móvil"]
precios_iniciales = dict.fromkeys(productos, 0)
print(precios_iniciales)

Iteración sobre diccionarios

Hay varias formas de recorrer un diccionario:

puntuaciones = {
    "Ana": 95,
    "Luis": 88,
    "Carmen": 92,
    "Pedro": 78
}

# Iteración sobre las claves (comportamiento predeterminado)
print("Estudiantes:")
for estudiante in puntuaciones:
    print(estudiante)

# Iteración sobre los valores
print("\nPuntuaciones:")
for puntuacion in puntuaciones.values():
    print(puntuacion)

# Iteración sobre pares clave-valor
print("\nEstudiantes y puntuaciones:")
for estudiante, puntuacion in puntuaciones.items():
    print(f"{estudiante}: {puntuacion}")

# Encontrar la puntuación máxima
mejor_estudiante = max(puntuaciones, key=puntuaciones.get)
print(f"\nMejor estudiante: {mejor_estudiante} con {puntuaciones[mejor_estudiante]} puntos")

Diccionarios anidados

Los diccionarios pueden contener otros diccionarios como valores, lo que permite estructuras de datos más complejas:

empleados = {
    "E001": {
        "nombre": "María",
        "departamento": "Ventas",
        "salario": 2500,
        "contacto": {
            "email": "maria@empresa.com",
            "telefono": "666-555-444"
        }
    },
    "E002": {
        "nombre": "Juan",
        "departamento": "IT",
        "salario": 2800,
        "contacto": {
            "email": "juan@empresa.com",
            "telefono": "666-777-888"
        }
    }
}

# Acceso a datos anidados
print(empleados["E001"]["nombre"])  # Salida: María
print(empleados["E002"]["contacto"]["email"])  # Salida: juan@empresa.com

# Modificación de datos anidados
empleados["E001"]["salario"] = 2700
print(empleados["E001"]["salario"])  # Salida: 2700

# Añadir un nuevo nivel
empleados["E001"]["historial"] = {"2023": "Excelente", "2022": "Bueno"}
print(empleados["E001"]["historial"]["2023"])  # Salida: Excelente

Comprensión de diccionarios

Similar a la comprensión de listas, Python permite crear diccionarios de forma concisa mediante la comprensión de diccionarios:

# Lista de números
numeros = [1, 2, 3, 4, 5]

# Crear un diccionario donde las claves son los números y los valores son sus cuadrados
cuadrados = {n: n**2 for n in numeros}
print(cuadrados)  # Salida: {1: 1, 2: 4, 3: 9, 4: 16, 5: 25}

# Comprensión con condición
pares_cuadrados = {n: n**2 for n in numeros if n % 2 == 0}
print(pares_cuadrados)  # Salida: {2: 4, 4: 16}

# Convertir dos listas en un diccionario
frutas = ["manzana", "plátano", "naranja", "uva"]
precios = [1.2, 0.9, 1.5, 2.3]
frutas_precios = {fruta: precio for fruta, precio in zip(frutas, precios)}
print(frutas_precios)

Restricciones en las claves de un diccionario

Es importante destacar que las claves de un diccionario deben ser inmutables. Esto significa que podemos usar:

  • Números (enteros, flotantes, complejos)
  • Cadenas de texto
  • Tuplas (siempre que contengan solo elementos inmutables)
  • Frozensets

Pero no podemos usar:

  • Listas
  • Diccionarios
  • Sets normales
# Claves válidas
diccionario_valido = {
    100: "cien",
    "clave": "valor",
    (1, 2): "tupla como clave",
    frozenset([1, 2, 3]): "conjunto inmutable como clave"
}

# Claves inválidas generarán error
try:
    diccionario_invalido = {[1, 2, 3]: "esto causará error"}
except TypeError as e:
    print(f"Error: {e}")  # Salida: Error: unhashable type: 'list'

Casos de uso comunes de diccionarios

Los diccionarios son extremadamente útiles en muchos escenarios:

1. Contadores

# Contar ocurrencias de palabras en un texto
texto = "el perro persigue al gato y el gato corre asustado porque el perro ladra"
palabras = texto.split()

contador = {}
for palabra in palabras:
    contador[palabra] = contador.get(palabra, 0) + 1

print(contador)

2. Mapeo de valores

# Traducción de palabras
traductor = {
    "casa": "house",
    "perro": "dog",
    "gato": "cat",
    "libro": "book"
}

frase = ["el", "perro", "y", "el", "gato", "están", "en", "casa"]
traduccion = [traductor.get(palabra, palabra) for palabra in frase]
print(" ".join(traduccion))

3. Caché o memorización

# Memorización de resultados de fibonacci
def fibonacci_con_memo():
    memo = {0: 0, 1: 1}  # Casos base
    
    def fib(n):
        if n not in memo:
            memo[n] = fib(n-1) + fib(n-2)
        return memo[n]
    
    return fib

calcular_fib = fibonacci_con_memo()
print(calcular_fib(10))  # Salida: 55

4. Representación de objetos

# Representación de un blog post
post = {
    "id": 1,
    "titulo": "Introducción a Python",
    "autor": {
        "nombre": "Ana",
        "email": "ana@blog.com"
    },
    "contenido": "Python es un lenguaje...",
    "comentarios": [
        {"usuario": "Luis", "texto": "¡Gran artículo!"},
        {"usuario": "Elena", "texto": "Muy útil, gracias."}
    ],
    "tags": ["python", "programación", "tutorial"]
}

# Podemos acceder fácilmente a cualquier información
print(f"Título: {post['titulo']}")
print(f"Autor: {post['autor']['nombre']}")
print(f"Primer comentario: {post['comentarios'][0]['texto']}")

Conversión entre diccionarios y otras estructuras

Los diccionarios pueden convertirse a y desde otras estructuras de datos:

# Lista de tuplas a diccionario
items = [("a", 1), ("b", 2), ("c", 3)]
dict_desde_items = dict(items)
print(dict_desde_items)  # Salida: {'a': 1, 'b': 2, 'c': 3}

# Diccionario a lista de tuplas
items_desde_dict = list(dict_desde_items.items())
print(items_desde_dict)  # Salida: [('a', 1), ('b', 2), ('c', 3)]

# Listas separadas de claves y valores
claves = ["nombre", "edad", "ciudad"]
valores = ["Miguel", 30, "Barcelona"]

# Combinamos con zip
persona = dict(zip(claves, valores))
print(persona)  # Salida: {'nombre': 'Miguel', 'edad': 30, 'ciudad': 'Barcelona'}

Resumen

Los diccionarios son estructuras de datos fundamentales en Python que permiten almacenar información como pares clave-valor, ofreciendo un acceso eficiente a los datos mediante identificadores únicos. Su capacidad para modificarse, contener diversos tipos de datos (incluso otros diccionarios) y ofrecer métodos potentes para manipular la información los convierte en herramientas esenciales para el desarrollo de aplicaciones. A diferencia de las listas que están optimizadas para secuencias ordenadas, los diccionarios destacan en situaciones donde necesitamos buscar, actualizar o almacenar datos asociativos. En el próximo artículo exploraremos los conjuntos (sets), otra estructura de datos importante que nos permitirá trabajar con colecciones de elementos únicos y realizar operaciones matemáticas de conjuntos.