Lección Python

Contenido de la lección

Introducción

Contenido de la lección.

Objetivos de aprendizaje
  • Objetivo 1
  • Objetivo 2
  • Objetivo 3

Objetivos de Aprendizaje

Al finalizar este tema, serás capaz de:
  • Comprender la estructura y funcionamiento interno de los diccionarios en Python
  • Dominar los métodos fundamentales para crear, acceder y modificar diccionarios
  • Implementar soluciones eficientes utilizando diccionarios en problemas de ingeniería
  • Aplicar técnicas avanzadas como diccionarios anidados y comprensiones de diccionarios

📚 Conceptos Fundamentales de Diccionarios

Un diccionario en Python es una colección ordenada (desde Python 3.7+) de pares clave-valor. Las claves deben ser objetos inmutables (strings, números, tuplas) y únicas, mientras que los valores pueden ser de cualquier tipo. Los diccionarios son mutables, lo que significa que pueden modificarse después de su creación. La sintaxis básica utiliza llaves {} con pares clave:valor separados por comas. La eficiencia de acceso es O(1) en promedio, lo que los hace ideales para búsquedas rápidas. Esta estructura de datos implementa una tabla hash internamente, proporcionando un rendimiento excepcional para operaciones de búsqueda, inserción y eliminación.

Creación básica de diccionarios con diferentes tipos de datos Copiar
# Diccionario vacío
diccionario_vacio = {}
print('Diccionario vacío:', diccionario_vacio)

# Diccionario con datos iniciales
estudiante = {
    'nombre': 'Ana García',
    'edad': 21,
    'carrera': 'Ingeniería de Sistemas',
    'promedio': 9.2,
    'materias': ['Algoritmos', 'Bases de Datos', 'Python']
}
print('Estudiante:', estudiante)

# Usando el constructor dict()
config = dict(host='localhost', puerto=5432, debug=True)
print('Configuración:', config)
Diccionario vacío: {}
Estudiante: {'nombre': 'Ana García', 'edad': 21, 'carrera': 'Ingeniería de Sistemas', 'promedio': 9.2, 'materias': ['Algoritmos', 'Bases de Datos', 'Python']}
Configuración: {'host': 'localhost', 'puerto': 5432, 'debug': True}
Explicación: Se muestran tres formas de crear diccionarios: vacío, con datos iniciales y usando el constructor dict(). Observe cómo las claves pueden ser strings y los valores pueden ser de diferentes tipos.
Acceso y modificación de elementos en diccionarios Copiar
# Diccionario de ejemplo
producto = {'nombre': 'Laptop', 'precio': 1200.50, 'stock': 15}

# Acceso usando corchetes
print('Nombre del producto:', producto['nombre'])

# Acceso usando get() - método seguro
print('Precio:', producto.get('precio'))
print('Descuento:', producto.get('descuento', 0))  # Valor por defecto

# Modificación de valores existentes
producto['stock'] = 12
print('Stock actualizado:', producto['stock'])

# Agregar nuevas claves
producto['categoria'] = 'Electrónicos'
print('Producto completo:', producto)
Nombre del producto: Laptop
Precio: 1200.5
Descuento: 0
Stock actualizado: 12
Producto completo: {'nombre': 'Laptop', 'precio': 1200.5, 'stock': 12, 'categoria': 'Electrónicos'}
Explicación: El método get() es más seguro que los corchetes porque no genera error si la clave no existe. Permite especificar un valor por defecto. La asignación directa modifica valores existentes o crea nuevos.

🎯 Métodos Fundamentales de Diccionarios

Los diccionarios en Python ofrecen una amplia gama de métodos que facilitan la manipulación y consulta de datos. Los métodos keys(), values() e items() proporcionan vistas dinámicas del diccionario que se actualizan automáticamente. El método update() permite fusionar diccionarios eficientemente. Los métodos pop() y popitem() ofrecen diferentes formas de eliminar elementos. Estos métodos son esenciales para escribir código eficiente y legible, especialmente en aplicaciones que manejan grandes volúmenes de datos estructurados.

Métodos de consulta y iteración en diccionarios Copiar
# Diccionario de empleados
empleados = {
    'E001': {'nombre': 'Carlos Ruiz', 'departamento': 'IT', 'salario': 3500},
    'E002': {'nombre': 'María López', 'departamento': 'HR', 'salario': 3200},
    'E003': {'nombre': 'José García', 'departamento': 'IT', 'salario': 3800}
}

# Obtener todas las claves
print('IDs de empleados:', list(empleados.keys()))

# Iterar sobre claves y valores
print('\nInformación de empleados:')
for emp_id, datos in empleados.items():
    print(f'{emp_id}: {datos["nombre"]} - ${datos["salario"]}')

# Verificar existencia de clave
if 'E001' in empleados:
    print('\nEmpleado E001 encontrado')

# Contar elementos
print(f'Total de empleados: {len(empleados)}')
IDs de empleados: ['E001', 'E002', 'E003']

Información de empleados:
E001: Carlos Ruiz - $3500
E002: María López - $3200
E003: José García - $3800

Empleado E001 encontrado
Total de empleados: 3
Explicación: Los métodos keys() e items() permiten iterar eficientemente sobre diccionarios. El operador 'in' verifica la existencia de claves de forma optimizada. len() devuelve el número de pares clave-valor.
Métodos de modificación y actualización de diccionarios Copiar
# Diccionario base de configuración
config_base = {'debug': False, 'timeout': 30, 'retries': 3}
print('Configuración base:', config_base)

# Actualizar con otro diccionario
config_desarrollo = {'debug': True, 'log_level': 'INFO', 'port': 8080}
config_base.update(config_desarrollo)
print('Después de update:', config_base)

# Eliminar elemento con pop()
timeout = config_base.pop('timeout')
print(f'Timeout eliminado: {timeout}')
print('Configuración actual:', config_base)

# Eliminar último elemento con popitem()
ultimo = config_base.popitem()
print(f'Último elemento eliminado: {ultimo}')
print('Configuración final:', config_base)

# Limpiar diccionario
config_temp = {'a': 1, 'b': 2}
config_temp.clear()
print('Después de clear:', config_temp)
Configuración base: {'debug': False, 'timeout': 30, 'retries': 3}
Después de update: {'debug': True, 'timeout': 30, 'retries': 3, 'log_level': 'INFO', 'port': 8080}
Timeout eliminado: 30
Configuración actual: {'debug': True, 'retries': 3, 'log_level': 'INFO', 'port': 8080}
Último elemento eliminado: ('port', 8080)
Configuración final: {'debug': True, 'retries': 3, 'log_level': 'INFO'}
Después de clear: {}
Explicación: update() fusiona diccionarios, sobrescribiendo valores existentes. pop() elimina y retorna el valor de una clave específica. popitem() elimina el último par clave-valor en Python 3.7+. clear() elimina todos los elementos.

💡 Casos de Uso Avanzados

Los diccionarios anidados permiten representar estructuras de datos complejas como árboles o grafos. Las comprensiones de diccionarios ofrecen una sintaxis concisa para crear diccionarios basados en iterables existentes. Los diccionarios como contadores implementan patrones comunes en análisis de datos. La combinación con funciones lambda y métodos como sorted() permite operaciones sofisticadas de procesamiento de datos. Estas técnicas son fundamentales en aplicaciones de análisis de datos, APIs REST y sistemas de configuración complejos.

Diccionarios anidados para estructuras de datos complejas Copiar
# Sistema de gestión universitaria
universidad = {
    'facultades': {
        'ingenieria': {
            'carreras': ['Sistemas', 'Civil', 'Industrial'],
            'decano': 'Dr. Rodríguez',
            'estudiantes': 1250
        },
        'ciencias': {
            'carreras': ['Matemáticas', 'Física', 'Química'],
            'decano': 'Dra. Martínez',
            'estudiantes': 890
        }
    }
}

# Acceso a datos anidados
print('Carreras de ingeniería:', universidad['facultades']['ingenieria']['carreras'])

# Agregar nueva información
universidad['facultades']['ingenieria']['ubicacion'] = 'Edificio A'

# Iterar sobre estructura anidada
print('\nResumen por facultad:')
for nombre_fac, datos_fac in universidad['facultades'].items():
    print(f'{nombre_fac.title()}: {datos_fac["estudiantes"]} estudiantes')
    print(f'  Decano: {datos_fac["decano"]}')
Carreras de ingeniería: ['Sistemas', 'Civil', 'Industrial']

Resumen por facultad:
Ingenieria: 1250 estudiantes
  Decano: Dr. Rodríguez
Ciencias: 890 estudiantes
  Decano: Dra. Martínez
Explicación: Los diccionarios anidados permiten representar jerarquías complejas. El acceso se realiza encadenando corchetes. Se pueden modificar y expandir dinámicamente para adaptar la estructura a nuevos requerimientos.
Comprensiones de diccionarios y análisis de datos Copiar
# Lista de productos con precios
productos = [('Laptop', 1200), ('Mouse', 25), ('Teclado', 75), ('Monitor', 300)]

# Comprensión básica - convertir a diccionario
precios = {producto: precio for producto, precio in productos}
print('Precios:', precios)

# Comprensión con condición - productos caros
productos_caros = {p: pr for p, pr in productos if pr > 100}
print('Productos caros:', productos_caros)

# Comprensión con transformación - descuentos
descuentos = {p: pr * 0.9 for p, pr in productos if pr > 50}
print('Precios con descuento:', descuentos)

# Análisis - contador de caracteres en nombres
contador_chars = {p: len(p) for p, _ in productos}
print('Caracteres por nombre:', contador_chars)

# Producto más caro usando max()
mas_caro = max(precios.items(), key=lambda item: item[1])
print(f'Producto más caro: {mas_caro[0]} - ${mas_caro[1]}')
Precios: {'Laptop': 1200, 'Mouse': 25, 'Teclado': 75, 'Monitor': 300}
Productos caros: {'Laptop': 1200, 'Monitor': 300}
Precios con descuento: {'Laptop': 1080.0, 'Teclado': 67.5, 'Monitor': 270.0}
Caracteres por nombre: {'Laptop': 6, 'Mouse': 5, 'Teclado': 7, 'Monitor': 7}
Producto más caro: Laptop - $1200
Explicación: Las comprensiones de diccionarios ofrecen sintaxis concisa para crear diccionarios. Se pueden aplicar condiciones y transformaciones. La función max() con key permite encontrar elementos basados en criterios específicos.

🔧 Optimización y Mejores Prácticas

La eficiencia en el uso de diccionarios implica considerar la complejidad temporal de las operaciones y la gestión de memoria. El uso de defaultdict del módulo collections simplifica el manejo de valores por defecto. Counter es ideal para operaciones de conteo. La elección correcta de tipos de datos para claves impacta el rendimiento. En aplicaciones críticas, es importante considerar la ordenación de diccionarios y el uso eficiente de memoria. Estas prácticas son especialmente importantes en sistemas de alto rendimiento y aplicaciones que procesan grandes volúmenes de datos.

Técnicas avanzadas con collections y optimización Copiar
from collections import defaultdict, Counter

# Agrupamiento eficiente con defaultdict
estudents_data = [
    ('Ana', 'Ingeniería', 85),
    ('Carlos', 'Matemáticas', 92),
    ('Elena', 'Ingeniería', 88),
    ('Diego', 'Matemáticas', 79)
]

# Agrupar por carrera
by_career = defaultdict(list)
for nombre, carrera, nota in students_data:
    by_career[carrera].append((nombre, nota))

print('Agrupado por carrera:')
for carrera, estudiantes in by_career.items():
    print(f'{carrera}: {estudiantes}')

# Contar frecuencias con Counter
text = 'python es un lenguaje de programacion python es genial'
word_count = Counter(text.split())
print('\nFrecuencia de palabras:')
print(dict(word_count))

# Palabras más comunes
print('\nPalabras más frecuentes:')
for palabra, freq in word_count.most_common(3):
    print(f'{palabra}: {freq} veces')
Agrupado por carrera:
Ingeniería: [('Ana', 85), ('Elena', 88)]
Matemáticas: [('Carlos', 92), ('Diego', 79)]

Frecuencia de palabras:
{'python': 2, 'es': 2, 'un': 1, 'lenguaje': 1, 'de': 1, 'programacion': 1, 'genial': 1}

Palabras más frecuentes:
python: 2 veces
es: 2 veces
un: 1 veces
Explicación: defaultdict evita errores KeyError al acceder claves inexistentes. Counter simplifica el conteo de elementos y ofrece métodos como most_common(). Estas herramientas mejoran la eficiencia y legibilidad del código.

Ejercicios Prácticos

Sistema de Inventario
INTERMEDIO

Descripción:

Crear un sistema de gestión de inventario usando diccionarios. Debe permitir agregar productos, actualizar stock, calcular valor total del inventario y generar reportes por categoría. Incluir validaciones para evitar stock negativo.

Pista: Usa diccionarios anidados para organizar productos por categorías. Implementa funciones separadas para cada operación del inventario.
Analizador de Texto
INTERMEDIO

Descripción:

Desarrollar un analizador que procese un texto y genere estadísticas: frecuencia de palabras, palabras más largas, caracteres más usados. Usar Counter y comprensiones de diccionarios para optimizar el análisis.

Pista: Combina Counter para frecuencias con comprensiones de diccionarios para filtros. Usa métodos como max() con key para encontrar extremos.
Base de Datos de Estudiantes
AVANZADO

Descripción:

Implementar un sistema que gestione información de estudiantes con materias, calificaciones y promedios. Debe calcular estadísticas por estudiante y materia, identificar estudiantes destacados y materias con mayor dificultad.

Pista: Usa defaultdict para agrupar datos automáticamente. Implementa funciones de cálculo de promedios y ordenamiento de resultados.
Optimizador de Configuraciones
AVANZADO

Descripción:

Crear un sistema que maneje configuraciones de aplicación con herencia y sobrescritura de valores. Debe soportar configuraciones por ambiente (desarrollo, producción) y validación de parámetros requeridos.

Pista: Usa el método update() para fusionar configuraciones. Implementa validación usando sets para verificar parámetros requeridos.

Resumen y Próximos Pasos

Los diccionarios son estructuras de datos fundamentales que proporcionan eficiencia y flexibilidad en el desarrollo de aplicaciones Python. Dominar su uso, desde operaciones básicas hasta técnicas avanzadas como comprensiones y collections especializadas, es esencial para escribir código eficiente y mantenible. En el siguiente tema exploraremos conjuntos (sets) y operaciones de conjunto, complementando nuestro conocimiento de estructuras de datos de Python para resolver problemas complejos de ingeniería de software.

🏷️ Etiquetas:
python diccionarios estructuras de datos programación ingeniería