Fundamentos del Control de Flujo

El control de flujo es el conjunto de mecanismos que definen el orden en que se llevan a cabo las instrucciones dentro de un programa.

En Python, el control de flujo se refiere a las estructuras que permiten decidir qué instrucciones ejecutar y cuántas veces repetirlas, modificando así la secuencia normal de ejecución del programa.

# Ejecución secuencial
x=5
y=6
resultado= x + y
print(resultado)
## 11

Fundamentos del control de flujo

Las estructuras de control de flujo nos permiten alterar este orden secuencial de tres maneras fundamentales:

Selección condicional: ejecutar diferentes bloques de código según se cumplan ciertas condiciones Iteración: repetir bloques de código un número determinado de veces o mientras se cumplan ciertas condiciones Transferencia de control: saltar a diferentes partes del código. #Importancia del Control de Flujo Automatización: Permite procesar grandes cantidades de datos sin intervención manual. Eficiencia: Evita la repetición innecesaria de código. Flexibilidad: Los programas pueden responder a diferentes situaciones. Escalabilidad: Facilita el manejo de problemas complejos. Interactividad: Permite crear programas que respondan dinámicamente. #Valores lógicos En el corazón de toda decisión computacional están los valores lógicos: TRUE y FALSE. Estos valores representan la verdad o falsedad de una proposición y son el fundamento sobre el cual se construyen todas las estructuras de control. En Python los valores lógicos son objetos de tipo bool (True, False) y se utilizan para controlar las decisiones dentro de un programa.

##Valores lógicos

# Los dos valores lógicos fundamentales
verdadero= True
falso= False
# verificar su clase 
print(type(True))  # <class 'bool'>
## <class 'bool'>
# verificar su clase
print(type(False)) # <class 'bool'>
## <class 'bool'>

En python no se puede usar las abreviaciones como en R

Operadores de comparación

Los operadores de comparación evalúan la relación entre dos valores y devuelven un resultado ‘bool’ #Igualdad y Desigualdad En Python (igual que en R y la mayoría de lenguajes): (=)se usa para asignar un valor a una variable. (==) se usa para comparar si dos valores son iguales.

# Operador de igualdad (==)
5==5 # True 
## True
print(5==3) #False
## False
print("hola" == "hola") # True
## True
print("Hola" == "hola") # False (Python distingue mayúsculas y minúsculas)
## False
# Operador de desigualdad (!=)
print(5!= 3) # True
## True
print(5!= 5) # False
## False
"gato" !="perro" #True
## True

Operadores de comparación

las comparaciones numéricas en Python siempre producen un resultado bool (True o False)

# Mayor que (>)
print(10 > 5) # True
## True
print(3 > 8)  # False   
## False
# Menor que (<)
print(2 < 7)  # True
## True
print(9 < 4)  # False
## False
# Mayor o igual que (>=)
print(5 >= 5)   # True
## True
print(5 >= 3)   # True
## True
print(2 >= 6)   # False
## False
# Menor o igual que (<=)
print(4 <= 4)   # True
## True
print(3 <= 7)   # True
## True
print(8 <= 2)   # False
## False

Operadores de comparación

las comparaciones numéricas en Python siempre producen un resultado bool (True o False)

edad = 25
limite = 18
# Comparaciones con variables
print(edad > limite) # True
## True
print(edad==limite) #False
## False
print(edad>=limite) #False
## True
precio = 150.00
descuento_minimo = 100.00
print(precio >= descuento_minimo) # True
## True

Operadores Lógicos

Los operadores lógicos permiten combinar múltiples condiciones bool: # El Operador AND En Python, el operador lógico and devuelve True solo si ambas condiciones son verdaderas; si al menos una es falsa, devuelve False.

# Tabla de verdad del operador and

print(True and True)    # True
## True
print(True and False)   # False
## False
print(False and True)   # False
## False
print(False and False)  # False
## False
edad = 25
tiene_licencia = True

# ¿Puede alquilar un auto? (debe ser mayor de 21 Y tener licencia)
puede_alquilar = (edad >= 21) and tiene_licencia
print(puede_alquilar)   # True
## True

#El Operador or En Python, el operador lógico or devuelve True si al menos una de las condiciones es verdadera; solo devuelve False cuando ambas condiciones son falsas.

# Tabla de verdad del operador or

print(True or True)    # True
## True
print(True or False)   # True
## True
print(False or True)   # True
## True
print(False or False)  # False
## False
es_estudiante = False
es_senior = True

# ¿Tiene descuento? (si es estudiante O es senior)
tiene_descuento = es_estudiante or es_senior
print(tiene_descuento)   # True
## True

El Operador not

En Python, el operador lógico not invierte el valor de verdad: convierte True en False y False en True.

# El operador not
print(not True)   # False
## False
print(not False)  # True
## True
# Ejemplo practico
esta_lloviendo = False
salir_sin_paraguas = not esta_lloviendo
print(salir_sin_paraguas)
## True

Combinaciones Complejas

En Python, las combinaciones complejas surgen cuando se usan varios operadores lógicos (and, or, not) junto con comparaciones dentro de una misma expresión. Estas combinaciones permiten evaluar condiciones más elaboradas y devuelven siempre un resultado booleano (True o False).

temperatura = 22
esta_soleado = True
es_fin_de_semana = True

# Es buen día para un fútbol
buen_dia_futbol = (temperatura >= 20) and esta_soleado and es_fin_de_semana
print(buen_dia_futbol)   # True
## True
# Usando paréntesis para claridad
nota1 = 85
nota2 = 78
asistencia = 95

aprobado = ((nota1 >= 70) and (nota2 >= 70)) and (asistencia >= 80)
print(aprobado)   # True
## True

Estructuras Condicionales

Estructuras Condicionales

El control condicional es la base de todo algoritmo. Permite que un programa “tome decisiones” según el valor de expresiones lógicas.

#La declaración if La estructura if es la forma más básica de control condicional. Permite que el programa ejecute código solo cuando se cumple una condición específica.Es como decir: “Si esto es verdad, entonces haz aquello”.

Estructura General

En Python, la condición de un if debe ser una expresión que se evalúe como True o False. Si la condición es True, se ejecuta el bloque de código indentado; si es False, ese bloque se ignora.

# if condición:
#     código a ejecutar si la condición es True
#Ejemplo
temperatura = 30
if temperatura > 25:
 print("Hace calor hoy")
## Hace calor hoy

En este ejemplo:

En Python, cuando usamos una instrucción if, primero se evalúa la condición (por ejemplo, temperatura > 25); si el resultado es True, se ejecuta el bloque de código indentado dentro del if, y si es False, el bloque se omite y el programa continúa normalmente, lo que significa que solo se ejecutan las instrucciones cuando la condición realmente se cumple.

Verificacion de edad

edad=18
if edad>=18:
 print("puedes votar en las elecciones")
 print("Tambien puedes obtener una licencia de conducir")
## puedes votar en las elecciones
## Tambien puedes obtener una licencia de conducir
# Si edad fuera 16, no se imprimiría nada

Control de Inventario

stock = 25
stock_minimo = 10

if stock < stock_minimo:
    print("¡ALERTA! Stock bajo - necesita reabastecimiento")
    urgente = True
# En este caso, como 25 >= 10, no se ejecuta el if

Validación de Datos

salario = 50000

if salario > 0:
    print("Salario válido registrado")
    salario_mensual = salario / 12
    print("Salario mensual:", round(salario_mensual, 2))
## Salario válido registrado
## Salario mensual: 4166.67

Forma Compacta

En Python, si un if tiene solo una instrucción, basta con escribir esa línea indentada; no se necesitan llaves ni líneas adicionales.

temperatura = 35
if temperatura > 30:
    print("Día muy caluroso")
## Día muy caluroso
# Forma compacta para una sola instrucción
if temperatura > 30: print("Día muy caluroso")
## Día muy caluroso

Notas importantes en Python:

No existen llaves { }, la indentación define los bloques. Para una sola instrucción, puedes escribirla en la misma línea del if usando : Para múltiples instrucciones, todas deben estar indentadas bajo el if.

# Definir la variable
es_viernes = True
# CORRECTO: múltiples instrucciones con indentación
if es_viernes:
 print("¡Por fin viernes!")
 preparar_fin_de_semana = True
 revisar_agenda_lunes = True
## ¡Por fin viernes!
es_viernes = True
# INCORRECTO: múltiples instrucciones sin indentación
if es_viernes:
    print("¡Por fin viernes!")  # Solo esta línea depende del if
## ¡Por fin viernes!
preparar_fin_de_semana = True   # Esta línea SIEMPRE se ejecuta, no depende del if

Caso de Uso

nivel_bateria = 15

if nivel_bateria <= 20:
    print("ADVERTENCIA: Batería baja")
    
    if nivel_bateria <= 10:
        print("CRÍTICO: Conectar cargador inmediatamente")
        modo_ahorro_energia = True
## ADVERTENCIA: Batería baja

Procesamiento Condicional de Datos

datos_usuario = [23, 45, 67, None, 89, 12]
# Verificar si hay valores faltantes
if any(dato is None for dato in datos_usuario):
    print("Detectados valores faltantes en los datos")
    # Contar valores faltantes
    valores_na = sum(1 for dato in datos_usuario if dato is None)
    print("Número de valores NA:", valores_na)
    # Crear versión limpia de los datos (sin valores faltantes)
    datos_limpios = [dato for dato in datos_usuario if dato is not None]
    print("Datos limpios:", ", ".join(str(dato) for dato in datos_limpios))
## Detectados valores faltantes en los datos
## Número de valores NA: 1
## Datos limpios: 23, 45, 67, 89, 12

Validación de Entrada de Usuario

# Simulando entrada de usuario
entrada = "25"        

if isinstance(entrada, str):
    # Intentar convertir a número
    try:
        numero = float(entrada)
    except ValueError:
        numero = None

    if numero is not None:
        print("Conversión exitosa:", numero)
        
        if numero >= 0:
            print("Número válido y positivo")
            resultado = numero ** 0.5
            print("Raíz cuadrada:", round(resultado, 2))
## Conversión exitosa: 25.0
## Número válido y positivo
## Raíz cuadrada: 5.0

Declaraciones else

En Python, la estructura if-else permite ejecutar un bloque de código si la condición es True y otro bloque diferente si la condición es False. Es útil cuando queremos elegir entre dos caminos mutuamente excluyentes. A diferencia de R, en Python no se usan llaves { }, sino que se indican los bloques mediante indentación.

condicion = True  # o False, o alguna expresión lógica

if condicion:
    print("La condición es True")
else:
    print("La condición es False")
## La condición es True
edad = 16

if edad >= 18:
    print("Eres mayor de edad")
    print("puedes votar")
else:
    print("No eres mayor de edad")
    print("no puedes votar")
## No eres mayor de edad
## no puedes votar
# Como edad = 16, se ejecuta el bloque else:
# "No eres mayot de edad"
# "No puedes votar"

if-else para Asignar Valores

Una técnica muy poderosa es usar if-else para asignar diferentes valores a una variable:

Método 1: Asignación Dentro de Cada Bloque

nota = 75

if nota >= 70:
    resultado = "Aprobado"
    mensaje = "¡Felicitaciones!"
else:
    resultado = "Reprobado"
    mensaje = "Necesitas estudiar más"

print(resultado)  # "Aprobado"
## Aprobado
print(mensaje) # "¡Felicitaciones!"
## ¡Felicitaciones!

Método 2: Asignación del Resultado Completo

nota = 65

estado = "Aprobado" if nota >= 70 else "Reprobado"
print(estado)  # "Reprobado"
## Reprobado
# Tambien funciona con calculos mas complejos
precio_base = 100
es_miembro = True

precio_final = precio_base * 0.9 if es_miembro else precio_base

print(precio_final)  # 90
## 90.0

Sistema de Calificación de Crédito

puntaje_credito = 650

if puntaje_credito >= 700:
    categoria = "Excelente"
    tasa_interes = 3.5
    limite_credito = 50000
    aprobacion_automatica = True
else:
    categoria = "Regular"
    tasa_interes = 8.5
    limite_credito = 15000
    aprobacion_automatica = False

print("Categoría:", categoria)
## Categoría: Regular
print("Tasa de interés:", tasa_interes, "%") 
## Tasa de interés: 8.5 %
print("Límite de crédito: $", limite_credito) 
## Límite de crédito: $ 15000
print("Aprobación automática:", aprobacion_automatica) 
## Aprobación automática: False

Calculadora de Descuentos

monto_compra = 150
descuento_aplicado = 0

if monto_compra >= 100:
    descuento_aplicado = monto_compra * 0.15  # 15% de descuento
    tipo_descuento = "Compra Mayor"
    puntos_ganados = monto_compra * 2  # Doble puntos
else:
    descuento_aplicado = 0
    tipo_descuento = "Sin descuento"
    puntos_ganados = monto_compra  # Puntos normales

monto_final = monto_compra - descuento_aplicado

print("Monto original: $", monto_compra)
## Monto original: $ 150
print("Puntos ganados:", puntos_ganados)
## Puntos ganados: 300
print("Descuento: $", round(descuento_aplicado, 2))
## Descuento: $ 22.5
print("Monto final: $", round(monto_final, 2))
## Monto final: $ 127.5
print("Tipo:", tipo_descuento)
## Tipo: Compra Mayor

Sistema de Recomendación de Ropa

temperatura = 18
precipitacion = 0  # mm de lluvia

if temperatura >= 25:
    ropa_recomendada = "Camiseta y pantalón corto"
    accesorios = ["gorra", "lentes de sol"]
    calzado = "sandalias o tenis ligeros"
else:
    ropa_recomendada = "Suéter y pantalón largo"
    accesorios = ["bufanda", "guantes"]
    calzado = "zapatos cerrados"

# Verificar lluvia independientemente de la temperatura
if precipitacion > 0:
    accesorios.extend(["paraguas", "impermeable"])
    calzado = "botas impermeables"
print("Ropa recomendada:", ropa_recomendada)
## Ropa recomendada: Suéter y pantalón largo
print("Accesorios:", ", ".join(accesorios))
## Accesorios: bufanda, guantes
print("Calzado:", calzado)
## Calzado: zapatos cerrados

Validación y Manejo de Errores

dividendo = 10
divisor = 3

if divisor != 0:
    resultado = dividendo / divisor
    print(f"El resultado de {dividendo} ÷ {divisor} es: {round(resultado, 2)}")
else:
    print("Error: No se puede dividir por cero")
    resultado = None
## El resultado de 10 ÷ 3 es: 3.33

Validación de Tipos de Datos

entrada_usuario = "123"

# Verificar si la entrada ya es un número
if isinstance(entrada_usuario, (int, float)):
    print("Entrada válida: es un número")
    numero_procesado = entrada_usuario * 2
    print("Resultado:", numero_procesado)
else:
    print("Entrada inválida: no es un número")
    
    # Intentar convertir a número
    try:
        numero_convertido = float(entrada_usuario)
    except ValueError:
        numero_convertido = None
    
    if numero_convertido is not None:
        print("Conversión exitosa")
        numero_procesado = numero_convertido * 2
        print("Resultado:", numero_procesado)
    else:
        print("No se pudo convertir a número")
        numero_procesado = 0
## Entrada inválida: no es un número
## Conversión exitosa
## Resultado: 246.0

Sistema de Autenticación Básico

from datetime import datetime

usuario_ingresado = "admin"
password_ingresado = "12345"

# Credenciales correctas (en un sistema real, estarían encriptadas)
usuario_correcto = "admin"
password_correcto = "admin123"

# Verificar credenciales
if usuario_ingresado == usuario_correcto and password_ingresado == password_correcto:
    print("Acceso concedido")
    sesion_activa = True
    tiempo_sesion = datetime.now()
    permisos = ["leer", "escribir", "administrar"]
    print("Bienvenido,", usuario_correcto)
    print("Hora de inicio de sesión:", tiempo_sesion)
else:
    print("Acceso denegado: credenciales incorrectas")
    sesion_activa = False
    intentos_fallidos = 1  # En un sistema real, incrementarías un contador

    # Determinar qué falló
    if usuario_ingresado != usuario_correcto:
        print("Usuario incorrecto")
    if password_ingresado != password_correcto:
        print("Contraseña incorrecta")
## Acceso denegado: credenciales incorrectas
## Contraseña incorrecta

Múltiples Condiciones con if-else if-else

La función if-else

Cuando se tiene más de dos opciones mutuamente excluyentes, es necesario una estructura que pueda manejar múltiples condiciones. La estructura if-else permite crear una cadena de decisiones donde solo una de las opciones se ejecutará. # Estructura General

primera_condicion = False
segunda_condicion = True
tercera_condicion = False

if primera_condicion:
    print("Se cumple la primera condición")
elif segunda_condicion:
    print("Se cumple la segunda condición")
elif tercera_condicion:
    print("Se cumple la tercera condición")
else:
    print("No se cumple ninguna condición")
## Se cumple la segunda condición

Las condiciones en un bloque if-elif-else se evalúan de arriba hacia abajo.

En cuanto Python encuentra la primera condición verdadera (True), ejecuta solo ese bloque y omite las demás.

Si ninguna condición es verdadera, se ejecuta el bloque else (si existe).

Ejemplo

nota = 85

if nota >= 90:
    calificacion = "A"
    comentario = "Excelente trabajo"
elif nota >= 80:  # Solo se evalúa si nota < 90
    calificacion = "B"
    comentario = "Muy buen trabajo"
elif nota >= 70:  # Solo se evalúa si nota < 80
    calificacion = "C"
    comentario = "Trabajo satisfactorio"
elif nota >= 60:  # Solo se evalúa si nota < 70
    calificacion = "D"
    comentario = "Necesita mejorar"
else:  # Solo se ejecuta si nota < 60
    calificacion = "F"
    comentario = "Debe repetir el curso"

print("Calificación:", calificacion)
## Calificación: B
# Salida: Calificación: B
print(comentario)
## Muy buen trabajo

La Importancia del Orden

El orden de las condiciones es crucial. Siempre ordena de más específico a menos específico, o de mayor a menor (o viceversa):

numero = 75
# CORRECTO: de mayor a menor
if numero >= 90:
    categoria = "Muy alto"
elif numero >= 70:  # 75 >= 70 es True, se ejecuta aquí
    categoria = "Alto"  # Resultado correcto
elif numero >= 50:
    categoria = "Medio"  # Ya no se evalúa
else:
    categoria = "Bajo"

print(categoria) 
## Alto
# INCORRECTO: de menor a mayor
if numero >= 50:  # 75 >= 50 es True, se ejecuta aquí
    categoria_mala = "Medio"  # Resultado incorrecto
elif numero >= 70:
    categoria_mala = "Alto"  # Nunca se ejecuta
elif numero >= 90:
    categoria_mala = "Muy alto"  # Nunca se ejecuta

print(categoria_mala) # "Medio"
## Medio

Sistema de Clasificación de IMC

peso = 70  # kg
altura = 1.75  # metros

imc = peso / (altura ** 2)  # ** es el operador de potencia en Python

if imc < 18.5:
    categoria = "Bajo peso"
    recomendacion = "Consulte con un nutricionista para ganar peso saludablemente"
    color_alerta = "azul"
elif imc < 25:
    categoria = "Peso normal"
    recomendacion = "Mantenga su estilo de vida saludable"
    color_alerta = "verde"
elif imc < 30:
    categoria = "Sobrepeso"
    recomendacion = "Considere aumentar la actividad física y mejorar la dieta"
    color_alerta = "amarillo"
elif imc < 35:
    categoria = "Obesidad clase I"
    recomendacion = "Consulte con un médico para un plan de pérdida de peso"
    color_alerta = "naranja"
elif imc < 40:
    categoria = "Obesidad clase II"
    recomendacion = "Es importante consultar con un médico especialista"
    color_alerta = "rojo"
else:
    categoria = "Obesidad clase III (mórbida)"
    recomendacion = "Consulte urgentemente con un médico especialista"
    color_alerta = "rojo_intenso"

print("IMC:", round(imc, 2))
## IMC: 22.86
print(f"Categoría: {categoria}")
## Categoría: Peso normal
print(f"Recomendación: {recomendacion}")
## Recomendación: Mantenga su estilo de vida saludable
print(f"Nivel de alerta: {color_alerta}")
## Nivel de alerta: verde

Sistema de Tarifas Progresivas

consumo_kwh = 250  # kilowatts-hora consumidos

# Tarifas escalonadas (precios por kWh)
if consumo_kwh <= 100:
    # Tarifa básica: primeros 100 kWh
    tarifa = 0.12
    costo = consumo_kwh * tarifa
    tipo_usuario = "Básico"
elif consumo_kwh <= 200:
    # Tarifa intermedia: de 101 a 200 kWh
    costo_basico = 100 * 0.12
    consumo_intermedio = consumo_kwh - 100
    costo_intermedio = consumo_intermedio * 0.18
    costo = costo_basico + costo_intermedio
    tipo_usuario = "Intermedio"
elif consumo_kwh <= 300:
    # Tarifa alta: de 201 a 300 kWh
    costo_basico = 100 * 0.12
    costo_intermedio = 100 * 0.18
    consumo_alto = consumo_kwh - 200
    costo_alto = consumo_alto * 0.25
    costo = costo_basico + costo_intermedio + costo_alto
    tipo_usuario = "Alto"
else:
    # Tarifa muy alta: más de 300 kWh
    costo_basico = 100 * 0.12
    costo_intermedio = 100 * 0.18
    costo_alto = 100 * 0.25
    consumo_muy_alto = consumo_kwh - 300
    costo_muy_alto = consumo_muy_alto * 0.32
    costo = costo_basico + costo_intermedio + costo_alto + costo_muy_alto
    tipo_usuario = "Muy Alto"

print("Consumo:", consumo_kwh, "kWh")
## Consumo: 250 kWh
print(f"Tipo de usuario: {tipo_usuario}")
## Tipo de usuario: Alto
print(f"Costo total: ${round(costo, 2)}")
## Costo total: $42.5
print(f"Precio promedio por kWh: ${round(costo / consumo_kwh, 4)}")
## Precio promedio por kWh: $0.17

Sistema de Evaluación Académica Complejo

# Datos del estudiante
nota_examenes = 85
nota_tareas = 78
asistencia = 95
participacion = 88
proyecto_final = 92

# Cálculo de nota ponderada
nota_final = (nota_examenes * 0.4) + (nota_tareas * 0.25) + \
             (asistencia * 0.1) + (participacion * 0.1) + \
             (proyecto_final * 0.15)

# Clasificación de la nota final
if nota_final >= 95:
    letra = "A+"
    puntos = 4.0
    descripcion = "Excelencia sobresaliente"
    mencion = "Suma Cum Laude"
elif nota_final >= 90:
    letra = "A"
    puntos = 4.0
    descripcion = "Excelente desempeño"
    mencion = "Magna Cum Laude"
elif nota_final >= 87:
    letra = "A-"
    puntos = 3.7
    descripcion = "Muy buen desempeño"
    mencion = "Cum Laude"
elif nota_final >= 83:
    letra = "B+"
    puntos = 3.3
    descripcion = "Buen desempeño superior"
    mencion = "Sin mención especial"
elif nota_final >= 80:
    letra = "B"
    puntos = 3.0
    descripcion = "Buen desempeño"
    mencion = "Sin mención especial"
elif nota_final >= 77:
    letra = "B-"
    puntos = 2.7
    descripcion = "Desempeño satisfactorio superior"
    mencion = "Sin mención especial"
elif nota_final >= 73:
    letra = "C+"
    puntos = 2.3
    descripcion = "Desempeño satisfactorio"
    mencion = "Sin mención especial"
elif nota_final >= 70:
    letra = "C"
    puntos = 2.0
    descripcion = "Desempeño mínimo aceptable"
    mencion = "Sin mención especial"
elif nota_final >= 65:
    letra = "D"
    puntos = 1.0
    descripcion = "Desempeño deficiente"
    mencion = "Requiere recuperación"
else:
    letra = "F"
    puntos = 0.0
    descripcion = "Desempeño insuficiente"
    mencion = "Debe repetir el curso"

# Modificadores por asistencia
if asistencia < 75:
    mencion += " - BAJA ASISTENCIA"
    if puntos > 0:
        puntos -= 0.5  # Penalización

print("=== REPORTE ACADÉMICO ===")
## === REPORTE ACADÉMICO ===
print(f"Nota final: {round(nota_final, 2)}")
## Nota final: 85.6
print(f"Calificación: {letra}")
## Calificación: B+
print(f"Puntos GPA: {puntos}")
## Puntos GPA: 3.3
print(f"Descripción: {descripcion}")
## Descripción: Buen desempeño superior
print(f"Mención: {mencion}")
## Mención: Sin mención especial

Sistema de Clasificación Meteorológica

temperatura = 22
humedad = 65
velocidad_viento = 15  # km/h
precipitacion = 2  # mm

# Clasificación principal por temperatura
if temperatura < -10:
    clima_base = "Extremadamente frío"
    actividades = "Permanecer en interiores"
elif temperatura < 0:
    clima_base = "Muy frío"
    actividades = "Deportes de invierno, ropa térmica"
elif temperatura < 10:
    clima_base = "Frío"
    actividades = "Caminatas con abrigo, actividades interiores"
elif temperatura < 20:
    clima_base = "Fresco"
    actividades = "Senderismo, actividades al aire libre con chaqueta"
elif temperatura < 25:
    clima_base = "Templado"
    actividades = "Ideal para todas las actividades al aire libre"
elif temperatura < 30:
    clima_base = "Cálido"
    actividades = "Playa, piscina, deportes acuáticos"
elif temperatura < 35:
    clima_base = "Caluroso"
    actividades = "Actividades acuáticas, evitar ejercicio intenso"
else:
    clima_base = "Extremadamente caluroso"
    actividades = "Permanecer en interiores con aire acondicionado"
print(f"Temperatura: {temperatura} °C")
## Temperatura: 22 °C
print(f"Humedad: {humedad}%")
## Humedad: 65%
print(f"Velocidad del viento: {velocidad_viento} km/h")
## Velocidad del viento: 15 km/h
print(f"Precipitación: {precipitacion} mm")
## Precipitación: 2 mm
print(f"Clasificación del clima: {clima_base}")
## Clasificación del clima: Templado
print(f"Actividades recomendadas: {actividades}")
## Actividades recomendadas: Ideal para todas las actividades al aire libre

ifelse

ifelse() es la versión vectorizada de if-else. En Python no existe directamente un ifelse() vectorizado como en R, pero puedes lograr lo mismo usando listas por comprensión o NumPy para datos vectoriales.

# Vector de números
numeros = [-3, -1, 0, 2, 5, -7, 8]

# Aplicar condición a todo el vector (equivalente a ifelse)
signos = ["No negativo" if x >= 0 else "Negativo" for x in numeros]

# Mostrar resultados uno por uno
for num, sig in zip(numeros, signos):
    print(f"Número: {num}, Signo: {sig}")
## Número: -3, Signo: Negativo
## Número: -1, Signo: Negativo
## Número: 0, Signo: No negativo
## Número: 2, Signo: No negativo
## Número: 5, Signo: No negativo
## Número: -7, Signo: Negativo
## Número: 8, Signo: No negativo

Comparación con Métodos Alternativos

numeros = [-3, -1, 0, 2, 5, -7, 8]

# Método tradicional con bucle (más lento)
signos_bucle = [None] * len(numeros) 
for i in range(len(numeros)):
    if numeros[i] >= 0:
        signos_bucle[i] = "No negativo"
    else:
        signos_bucle[i] = "Negativo"

signos_vectorizado = ["No negativo" if x >= 0 else "Negativo" for x in numeros]
print(signos_bucle == signos_vectorizado)  
## True
for num, sig in zip(numeros, signos_bucle):
    print(f"Número: {num}, Signo: {sig}")
## Número: -3, Signo: Negativo
## Número: -1, Signo: Negativo
## Número: 0, Signo: No negativo
## Número: 2, Signo: No negativo
## Número: 5, Signo: No negativo
## Número: -7, Signo: Negativo
## Número: 8, Signo: No negativo

Usando ifelse (Método Eficiente)

# Método vectorizado con lista por comprensión (más rápido)
signos_ifelse = ["No negativo" if x >= 0 else "Negativo" for x in numeros]

# Verificar que ambos métodos dan el mismo resultado
print(signos_bucle == signos_ifelse)  # True 
## True
for num, sig in zip(numeros, signos_ifelse):
    print(f"Número: {num}, Signo: {sig}")
## Número: -3, Signo: Negativo
## Número: -1, Signo: Negativo
## Número: 0, Signo: No negativo
## Número: 2, Signo: No negativo
## Número: 5, Signo: No negativo
## Número: -7, Signo: Negativo
## Número: 8, Signo: No negativo

Clasificación de Estudiantes

# Datos de estudiantes
estudiantes = ["Ana", "Pedro", "Luis", "María", "Carlos", "Sofia", "Diego", "Laura"]
notas = [95, 67, 82, 88, 45, 91, 73, 79]

# Clasificación simple: Aprobado/Reprobado
estado = ["Aprobado" if nota >= 70 else "Reprobado" for nota in notas]

# Crear "data frame" como lista de diccionarios
reporte_estudiantes = [
    {"nombre": nombre, "nota": nota, "estado": est}
    for nombre, nota, est in zip(estudiantes, notas, estado)
]

# Mostrar resultados
for fila in reporte_estudiantes:
    print(f"Nombre: {fila['nombre']}, Nota: {fila['nota']}, Estado: {fila['estado']}")
## Nombre: Ana, Nota: 95, Estado: Aprobado
## Nombre: Pedro, Nota: 67, Estado: Reprobado
## Nombre: Luis, Nota: 82, Estado: Aprobado
## Nombre: María, Nota: 88, Estado: Aprobado
## Nombre: Carlos, Nota: 45, Estado: Reprobado
## Nombre: Sofia, Nota: 91, Estado: Aprobado
## Nombre: Diego, Nota: 73, Estado: Aprobado
## Nombre: Laura, Nota: 79, Estado: Aprobado
necesita_recuperacion = ["Sí" if nota < 70 else "No" for nota in notas]
excelencia = ["Excelente" if nota >= 90 else "Regular" for nota in notas]

# Mostrar resultados
for i in range(len(estudiantes)):
    print("Nombre:", estudiantes[i])
    print("Nota:", notas[i])
    print("Estado:", estado[i])
    print("Necesita recuperación:", necesita_recuperacion[i])
    print("Excelencia:", excelencia[i])
## Nombre: Ana
## Nota: 95
## Estado: Aprobado
## Necesita recuperación: No
## Excelencia: Excelente
## Nombre: Pedro
## Nota: 67
## Estado: Reprobado
## Necesita recuperación: Sí
## Excelencia: Regular
## Nombre: Luis
## Nota: 82
## Estado: Aprobado
## Necesita recuperación: No
## Excelencia: Regular
## Nombre: María
## Nota: 88
## Estado: Aprobado
## Necesita recuperación: No
## Excelencia: Regular
## Nombre: Carlos
## Nota: 45
## Estado: Reprobado
## Necesita recuperación: Sí
## Excelencia: Regular
## Nombre: Sofia
## Nota: 91
## Estado: Aprobado
## Necesita recuperación: No
## Excelencia: Excelente
## Nombre: Diego
## Nota: 73
## Estado: Aprobado
## Necesita recuperación: No
## Excelencia: Regular
## Nombre: Laura
## Nota: 79
## Estado: Aprobado
## Necesita recuperación: No
## Excelencia: Regular

ifelse Anidado para Múltiples Categorías

Un if-else anidado permite aplicar múltiples condiciones en una sola expresión o bloque, asignando distintos resultados según cuál condición se cumpla primero. Es el equivalente a anidar varios ifelse() en R, pero usando if-elif-else o expresiones ternarias dentro de listas o variables.

edades = [5, 12, 15, 18, 25, 35, 45, 55, 65, 75, 85]

# Clasificación de edades con if-else anidado
categorias = [
    "Niño" if edad < 13 else
    "Adolescente" if edad < 18 else
    "Joven adulto" if edad < 25 else
    "Adulto" if edad < 65 else
    "Adulto mayor"
    for edad in edades
]

# Mostrar resultados
for i in range(len(edades)):
    print(f"Edad: {edades[i]}, Categoría: {categorias[i]}")
## Edad: 5, Categoría: Niño
## Edad: 12, Categoría: Niño
## Edad: 15, Categoría: Adolescente
## Edad: 18, Categoría: Joven adulto
## Edad: 25, Categoría: Adulto
## Edad: 35, Categoría: Adulto
## Edad: 45, Categoría: Adulto
## Edad: 55, Categoría: Adulto
## Edad: 65, Categoría: Adulto mayor
## Edad: 75, Categoría: Adulto mayor
## Edad: 85, Categoría: Adulto mayor
# Agregar recomendaciones específicas
recomendaciones = [
    "Educación primaria y juegos" if edad < 13 else
    "Educación secundaria" if edad < 18 else
    "Educación superior o trabajo" if edad < 25 else
    "Vida laboral activa" if edad < 65 else
    "Jubilación y cuidados"
    for edad in edades
]

# Mostrar resultados como tabla
print(f"{'Edad':>4} | {'Categoría':>15} | {'Recomendación':>30}")
## Edad |       Categoría |                  Recomendación
print("-"*55)
## -------------------------------------------------------
for i in range(len(edades)):
    print(f"{edades[i]:>4} | {categorias[i]:>15} | {recomendaciones[i]:>30}")
##    5 |            Niño |    Educación primaria y juegos
##   12 |            Niño |    Educación primaria y juegos
##   15 |     Adolescente |           Educación secundaria
##   18 |    Joven adulto |   Educación superior o trabajo
##   25 |          Adulto |            Vida laboral activa
##   35 |          Adulto |            Vida laboral activa
##   45 |          Adulto |            Vida laboral activa
##   55 |          Adulto |            Vida laboral activa
##   65 |    Adulto mayor |          Jubilación y cuidados
##   75 |    Adulto mayor |          Jubilación y cuidados
##   85 |    Adulto mayor |          Jubilación y cuidados

Sistema de Calificación Académica

# Datos de calificaciones
materias = ["Matemáticas", "Ciencias", "Historia", "Literatura", "Arte", "Deportes"]
puntuaciones = [95, 78, 85, 92, 68, 88]

# Sistema de calificación con letras
calificaciones_letra = [
    "A+" if nota >= 95 else
    "A" if nota >= 90 else
    "B+" if nota >= 85 else
    "B" if nota >= 80 else
    "C+" if nota >= 75 else
    "C" if nota >= 70 else
    "F"
    for nota in puntuaciones
]

# Determinar estado
estado_materia = ["Aprobada" if nota >= 70 else "Reprobada" for nota in puntuaciones]

# Calcular puntos GPA
puntos_gpa = [
    4.0 if nota >= 95 else
    4.0 if nota >= 90 else
    3.5 if nota >= 85 else
    3.0 if nota >= 80 else
    2.5 if nota >= 75 else
    2.0 if nota >= 70 else
    0.0
    for nota in puntuaciones
]

# Mostrar reporte completo
print(f"{'Materia':>12} | {'Puntaje':>7} | {'Letra':>4} | {'Estado':>9} | {'GPA':>3}")
##      Materia | Puntaje | Letra |    Estado | GPA
print("-"*50)
## --------------------------------------------------
for i in range(len(materias)):
    print(f"{materias[i]:>12} | {puntuaciones[i]:>7} | {calificaciones_letra[i]:>4} | {estado_materia[i]:>9} | {puntos_gpa[i]:>3}")
##  Matemáticas |      95 |   A+ |  Aprobada | 4.0
##     Ciencias |      78 |   C+ |  Aprobada | 2.5
##     Historia |      85 |   B+ |  Aprobada | 3.5
##   Literatura |      92 |    A |  Aprobada | 4.0
##         Arte |      68 |    F | Reprobada | 0.0
##     Deportes |      88 |   B+ |  Aprobada | 3.5
# Calcular estadísticas generales
promedio_general = sum(puntuaciones) / len(puntuaciones)
gpa_general = sum(puntos_gpa) / len(puntos_gpa)
materias_aprobadas = sum(1 for nota in puntuaciones if nota >= 70)
materias_reprobadas = sum(1 for nota in puntuaciones if nota < 70)

# Mostrar resultados
print(f"Promedio general: {round(promedio_general, 2)}")  
## Promedio general: 84.33
print(f"GPA general: {round(gpa_general, 2)}")         
## GPA general: 2.92
print(f"Materias aprobadas: {materias_aprobadas}")        
## Materias aprobadas: 5
print(f"Materias reprobadas: {materias_reprobadas}")      # 1
## Materias reprobadas: 1

Análisis de Ventas por Trimestre

# Datos de ventas mensuales
meses = ["Enero", "Febrero", "Marzo", "Abril", "Mayo", "Junio",
         "Julio", "Agosto", "Septiembre", "Octubre", "Noviembre", "Diciembre"]
ventas = [45000, 52000, 48000, 55000, 62000, 58000,
          71000, 68000, 59000, 63000, 75000, 82000]

# Meta mensual
meta_mensual = 60000

# Evaluación de rendimiento
rendimiento = []
for venta in ventas:
    if venta >= meta_mensual * 1.2:
        rendimiento.append("Excepcional")
    elif venta >= meta_mensual:
        rendimiento.append("Cumplió meta")
    elif venta >= meta_mensual * 0.8:
        rendimiento.append("Cerca de meta")
    else:
        rendimiento.append("Bajo rendimiento")

# Bonificación
bonificacion = []
for venta in ventas:
    if venta >= meta_mensual * 1.2:
        bonificacion.append(venta * 0.05)
    elif venta >= meta_mensual:
        bonificacion.append(venta * 0.03)
    else:
        bonificacion.append(0)

# Trimestres
trimestre = []
for mes in meses:
    if mes in ["Enero", "Febrero", "Marzo"]:
        trimestre.append("Q1")
    elif mes in ["Abril", "Mayo", "Junio"]:
        trimestre.append("Q2")
    elif mes in ["Julio", "Agosto", "Septiembre"]:
        trimestre.append("Q3")
    else:
        trimestre.append("Q4")

# Crear reporte de ventas
reporte_ventas = []
for i in range(len(meses)):
    reporte_ventas.append({
        "mes": meses[i],
        "trimestre": trimestre[i],
        "ventas": ventas[i],
        "meta": meta_mensual,
        "rendimiento": rendimiento[i],
        "bonificacion": round(bonificacion[i], 2)  # redondear a 2 decimales
    })

# Mostrar reporte
for fila in reporte_ventas:
    print(fila)
## {'mes': 'Enero', 'trimestre': 'Q1', 'ventas': 45000, 'meta': 60000, 'rendimiento': 'Bajo rendimiento', 'bonificacion': 0}
## {'mes': 'Febrero', 'trimestre': 'Q1', 'ventas': 52000, 'meta': 60000, 'rendimiento': 'Cerca de meta', 'bonificacion': 0}
## {'mes': 'Marzo', 'trimestre': 'Q1', 'ventas': 48000, 'meta': 60000, 'rendimiento': 'Cerca de meta', 'bonificacion': 0}
## {'mes': 'Abril', 'trimestre': 'Q2', 'ventas': 55000, 'meta': 60000, 'rendimiento': 'Cerca de meta', 'bonificacion': 0}
## {'mes': 'Mayo', 'trimestre': 'Q2', 'ventas': 62000, 'meta': 60000, 'rendimiento': 'Cumplió meta', 'bonificacion': 1860.0}
## {'mes': 'Junio', 'trimestre': 'Q2', 'ventas': 58000, 'meta': 60000, 'rendimiento': 'Cerca de meta', 'bonificacion': 0}
## {'mes': 'Julio', 'trimestre': 'Q3', 'ventas': 71000, 'meta': 60000, 'rendimiento': 'Cumplió meta', 'bonificacion': 2130.0}
## {'mes': 'Agosto', 'trimestre': 'Q3', 'ventas': 68000, 'meta': 60000, 'rendimiento': 'Cumplió meta', 'bonificacion': 2040.0}
## {'mes': 'Septiembre', 'trimestre': 'Q3', 'ventas': 59000, 'meta': 60000, 'rendimiento': 'Cerca de meta', 'bonificacion': 0}
## {'mes': 'Octubre', 'trimestre': 'Q4', 'ventas': 63000, 'meta': 60000, 'rendimiento': 'Cumplió meta', 'bonificacion': 1890.0}
## {'mes': 'Noviembre', 'trimestre': 'Q4', 'ventas': 75000, 'meta': 60000, 'rendimiento': 'Excepcional', 'bonificacion': 3750.0}
## {'mes': 'Diciembre', 'trimestre': 'Q4', 'ventas': 82000, 'meta': 60000, 'rendimiento': 'Excepcional', 'bonificacion': 4100.0}
# Inicializar sumas por trimestre
ventas_q1 = 0
ventas_q2 = 0
ventas_q3 = 0
ventas_q4 = 0

# Sumar ventas según el trimestre
for i in range(len(ventas)):
    if trimestre[i] == "Q1":
        ventas_q1 += ventas[i]
    elif trimestre[i] == "Q2":
        ventas_q2 += ventas[i]
    elif trimestre[i] == "Q3":
        ventas_q3 += ventas[i]
    elif trimestre[i] == "Q4":
        ventas_q4 += ventas[i]


print("Ventas Q1:", ventas_q1)
## Ventas Q1: 145000
print("Ventas Q2:", ventas_q2)
## Ventas Q2: 175000
print("Ventas Q3:", ventas_q3)
## Ventas Q3: 198000
print("Ventas Q4:", ventas_q4)
## Ventas Q4: 220000

Manejo de Valores Faltantes

# Datos
temperaturas = [22, 25, None, 18, 30, None, 15, 28, 24, None]
ciudades = ["Madrid", "Barcelona", "Valencia", "Sevilla", "Bilbao",
            "Málaga", "Zaragoza", "Murcia", "Palma", "Córdoba"]

# Inicializar listas para clasificación y ropa recomendada
clasificacion_temp = []
ropa_recomendada = []

# Clasificación y recomendación
for temp in temperaturas:
    if temp is None:
        clasificacion_temp.append("Sin datos")
        ropa_recomendada.append("Consultar pronóstico")
    elif temp >= 25:
        clasificacion_temp.append("Caluroso")
        ropa_recomendada.append("Ropa ligera")
    elif temp >= 20:
        clasificacion_temp.append("Templado")
        ropa_recomendada.append("Ropa normal")
    else:
        clasificacion_temp.append("Frío")
        ropa_recomendada.append("Abrigo")

# Crear reporte mereorologico
reporte_clima = []
for i in range(len(ciudades)):
    reporte_clima.append({
        "ciudad": ciudades[i],
        "temperatura": temperaturas[i],
        "clasificacion": clasificacion_temp[i],
        "ropa": ropa_recomendada[i]
    })


for fila in reporte_clima:
    print(fila)
## {'ciudad': 'Madrid', 'temperatura': 22, 'clasificacion': 'Templado', 'ropa': 'Ropa normal'}
## {'ciudad': 'Barcelona', 'temperatura': 25, 'clasificacion': 'Caluroso', 'ropa': 'Ropa ligera'}
## {'ciudad': 'Valencia', 'temperatura': None, 'clasificacion': 'Sin datos', 'ropa': 'Consultar pronóstico'}
## {'ciudad': 'Sevilla', 'temperatura': 18, 'clasificacion': 'Frío', 'ropa': 'Abrigo'}
## {'ciudad': 'Bilbao', 'temperatura': 30, 'clasificacion': 'Caluroso', 'ropa': 'Ropa ligera'}
## {'ciudad': 'Málaga', 'temperatura': None, 'clasificacion': 'Sin datos', 'ropa': 'Consultar pronóstico'}
## {'ciudad': 'Zaragoza', 'temperatura': 15, 'clasificacion': 'Frío', 'ropa': 'Abrigo'}
## {'ciudad': 'Murcia', 'temperatura': 28, 'clasificacion': 'Caluroso', 'ropa': 'Ropa ligera'}
## {'ciudad': 'Palma', 'temperatura': 24, 'clasificacion': 'Templado', 'ropa': 'Ropa normal'}
## {'ciudad': 'Córdoba', 'temperatura': None, 'clasificacion': 'Sin datos', 'ropa': 'Consultar pronóstico'}
# Estadísticas excluyendo NA (no None)
temp_validas = [t for t in temperaturas if t is not None]
promedio = sum(temp_validas) / len(temp_validas) if temp_validas else None

print(f"Temperatura promedio: {round(promedio, 1)} °C")
## Temperatura promedio: 23.1 °C
ciudades_con_datos = sum(1 for t in temperaturas if t is not None)
print(f"Ciudades con datos: {ciudades_con_datos}")
## Ciudades con datos: 7
ciudades_sin_datos = sum(1 for t in temperaturas if t is None)
print(f"Ciudades sin datos: {ciudades_sin_datos}")
## Ciudades sin datos: 3

La función switch

La función switch

En Python, aunque no existe una función switch() como en R, se puede lograr un comportamiento similar utilizando diccionarios o estructuras if-elif-else. Esta técnica permite comparar un valor con múltiples opciones conocidas y ejecutar diferentes acciones o devolver distintos resultados según la coincidencia. Es especialmente útil cuando hay muchas opciones específicas y cada una requiere un valor o acción distinta, ofreciendo una alternativa más limpia y eficiente que encadenar múltiples if-elif-else.

Estructura

Por nombres: usamos un diccionario con .get() para simular el switch de R.

opcion = "opcion2"

resultado_nombres = {
    "opcion1": "valor1",
    "opcion2": "valor2",
    "opcion3": "valor3"
}.get(opcion, "valor_por_defecto")  # valor por defecto si no coincide

print("Resultado por nombres:", resultado_nombres)
## Resultado por nombres: valor2
# --- Equivalente a switch por posiciones (numérico) ---
numero = 2  # corresponde a la posición en la lista
valores = ["valor1", "valor2", "valor3"]

# Para evitar error si el número está fuera de rango
if 1 <= numero <= len(valores):
    resultado_pos = valores[numero - 1]  # restamos 1 porque Python indexa desde 0
else:
    resultado_pos = "valor_por_defecto"

print("Resultado por posiciones:", resultado_pos)
## Resultado por posiciones: valor2

Ejemplo

# Determinar el número de días en un mes
mes = "febrero"
año = 2024  # Año bisiesto

# Función para determinar si un año es bisiesto
def es_bisiesto(a):
    return (a % 4 == 0) and (a % 100 != 0 or a % 400 == 0)

# Diccionario con los días de cada mes
dias_por_mes = {
    "enero": 31,
    "febrero": 29 if es_bisiesto(año) else 28,
    "marzo": 31,
    "abril": 30,
    "mayo": 31,
    "junio": 30,
    "julio": 31,
    "agosto": 31,
    "septiembre": 30,
    "octubre": 31,
    "noviembre": 30,
    "diciembre": 31
}

# Obtener los días del mes o NA si el mes no es válido
dias_en_mes = dias_por_mes.get(mes, "NA")

print(f"{mes.capitalize()} de {año} tiene {dias_en_mes} días")
## Febrero de 2024 tiene 29 días

Sistema de Días de la Semana

# Función para obtener información del día
def obtener_info_dia(dia):
    dia = dia.lower()  # Para hacer la comparación case-insensitive
    dias_info = {
        "lunes": {
            "nombre": "Lunes",
            "tipo": "Laboral",
            "actividad": "Comenzar la semana con energía",
            "estado_animo": "Motivado",
            "color": "Azul"
        },
        "martes": {
            "nombre": "Martes",
            "tipo": "Laboral",
            "actividad": "Continuar con el ritmo de trabajo",
            "estado_animo": "Concentrado",
            "color": "Verde"
        },
        "miercoles": {
            "nombre": "Miércoles",
            "tipo": "Laboral",
            "actividad": "Punto medio de la semana",
            "estado_animo": "Equilibrado",
            "color": "Amarillo"
        },
        "jueves": {
            "nombre": "Jueves",
            "tipo": "Laboral",
            "actividad": "Prepararse para el final de semana",
            "estado_animo": "Expectante",
            "color": "Naranja"
        },
        "viernes": {
            "nombre": "Viernes",
            "tipo": "Laboral",
            "actividad": "Finalizar tareas y planificar el fin de semana",
            "estado_animo": "Alegre",
            "color": "Rosa"
        },
        "sabado": {
            "nombre": "Sábado",
            "tipo": "Fin de semana",
            "actividad": "Relajarse y disfrutar tiempo libre",
            "estado_animo": "Relajado",
            "color": "Púrpura"
        },
        "domingo": {
            "nombre": "Domingo",
            "tipo": "Fin de semana",
            "actividad": "Descansar y prepararse para la nueva semana",
            "estado_animo": "Tranquilo",
            "color": "Rojo"
        }
    }

    # Retorna la info del día o un valor por defecto si no existe
    return dias_info.get(dia, {
        "nombre": "Desconocido",
        "tipo": "Inválido",
        "actividad": "Verificar el día ingresado",
        "estado_animo": "Confundido",
        "color": "Gris"
    })

# Ejemplo de uso
dia_actual = "viernes"
info_dia = obtener_info_dia(dia_actual)

print("Día:", info_dia["nombre"])
## Día: Viernes
print("Tipo:", info_dia["tipo"])
## Tipo: Laboral
print("Actividad:", info_dia["actividad"])
## Actividad: Finalizar tareas y planificar el fin de semana
print("Estado de ánimo:", info_dia["estado_animo"])
## Estado de ánimo: Alegre
print("Color:", info_dia["color"])
## Color: Rosa

Calculadora con switch

def calculadora(operacion, a, b):
    # Validar que los números sean válidos
    if not isinstance(a, (int, float)) or not isinstance(b, (int, float)):
        return {"resultado": None, "error": "Los operandos deben ser numéricos"}

    # Definir operaciones como diccionario (similar a switch)
    def division_safe(x, y):
        if y == 0:
            return {"resultado": None, "error": "División por cero"}
        return x / y

    def modulo_safe(x, y):
        if y == 0:
            return {"resultado": None, "error": "Módulo por cero"}
        return x % y

    operaciones = {
        "suma": lambda x, y: x + y,
        "+": lambda x, y: x + y,
        "resta": lambda x, y: x - y,
        "-": lambda x, y: x - y,
        "multiplicacion": lambda x, y: x * y,
        "*": lambda x, y: x * y,
        "division": division_safe,
        "/": division_safe,
        "potencia": lambda x, y: x ** y,
        "^": lambda x, y: x ** y,
        "modulo": modulo_safe,
        "%": modulo_safe
    }

    operacion_func = operaciones.get(operacion)
    if operacion_func is None:
        return {"resultado": None, "error": "Operación no reconocida"}

    # Ejecutar la operación
    resultado = operacion_func(a, b)
    # Si resultado ya es un diccionario (error), devolverlo tal cual
    if isinstance(resultado, dict):
        return resultado
    # Si es número, devolverlo con error None
    return {"resultado": resultado, "error": None}

# Ejemplo de uso
print(calculadora("suma", 10, 5)) # Suma
## {'resultado': 15, 'error': None}
print(calculadora("division", 10, 0)) # División por cero
## {'resultado': None, 'error': 'División por cero'}
print(calculadora("/", 15, 3))       # División válida
## {'resultado': 5.0, 'error': None}
print(calculadora("potencia", 2, 8)) # Potencia
## {'resultado': 256, 'error': None}
print(calculadora("xyz", 5, 3))      # Operación inválida
## {'resultado': None, 'error': 'Operación no reconocida'}

Sistema de Conversión de Unidades

def convertir_unidad(valor, de_unidad, a_unidad):
    # Normalizar unidades a minúsculas
    de = de_unidad.lower()
    a = a_unidad.lower()

    # Factores de conversión a metros (unidad base)
    factor_a_metros = {
        "mm": 0.001,
        "cm": 0.01,
        "m": 1,
        "km": 1000,
        "in": 0.0254,
        "ft": 0.3048,
        "yd": 0.9144,
        "mi": 1609.344
    }.get(de)

    factor_de_metros = {
        "mm": 1000,
        "cm": 100,
        "m": 1,
        "km": 0.001,
        "in": 39.3701,
        "ft": 3.28084,
        "yd": 1.09361,
        "mi": 0.000621371
    }.get(a)

    # Verificar unidades válidas
    if factor_a_metros is None or factor_de_metros is None:
        return {
            "resultado": None,
            "error": "Unidad no reconocida",
            "unidades_validas": ["mm", "cm", "m", "km", "in", "ft", "yd", "mi"]
        }

    # Realizar conversión
    metros = valor * factor_a_metros
    resultado_final = metros * factor_de_metros

    return {
        "valor_original": valor,
        "unidad_original": de_unidad,
        "valor_convertido": resultado_final,
        "unidad_final": a_unidad,
        "formula": f"{valor} {de_unidad} = {round(resultado_final, 6)} {a_unidad}"
    }

# Ejemplo de uso
print(convertir_unidad(100, "cm", "m"))
## {'valor_original': 100, 'unidad_original': 'cm', 'valor_convertido': 1.0, 'unidad_final': 'm', 'formula': '100 cm = 1.0 m'}
print(convertir_unidad(5, "ft", "m"))
## {'valor_original': 5, 'unidad_original': 'ft', 'valor_convertido': 1.524, 'unidad_final': 'm', 'formula': '5 ft = 1.524 m'}
print(convertir_unidad(10, "km", "mi"))
## {'valor_original': 10, 'unidad_original': 'km', 'valor_convertido': 6.21371, 'unidad_final': 'mi', 'formula': '10 km = 6.21371 mi'}
print(convertir_unidad(1, "xyz", "m")) # Unidad inválida
## {'resultado': None, 'error': 'Unidad no reconocida', 'unidades_validas': ['mm', 'cm', 'm', 'km', 'in', 'ft', 'yd', 'mi']}

Estructuras Iterativas

Bucles

Los bucles son estructuras que permiten ejecutar el mismo bloque de código múltiples veces sin tener que escribirlo repetidamente. Son fundamentales para automatizar tareas repetitivas y procesar conjuntos de datos. Imaginar que necesitas saludar a 100 personas. Sin bucles tendrías que escribir:

# Sin bucles (ineficiente e impráctico)
print("Hola persona 1")
## Hola persona 1
print("Hola persona 2")
## Hola persona 2
print("Hola persona 3")
## Hola persona 3
# ... 97 líneas más

Tipos de Bucles en Python

Un bucle en Python es una estructura de control que permite ejecutar repetidamente un bloque de código mientras se cumpla una condición o por un número determinado de veces.

En otras palabras, en lugar de escribir el mismo código varias veces, puedes usar un bucle para automatizar la repetición.

Características principales

Repetición automática: Ejecuta el mismo bloque varias veces sin necesidad de copiar el código.

Variable de control: Una variable que cambia en cada iteración y puede controlar cuándo termina el bucle.

Cuerpo del bucle: El bloque de código que se ejecuta en cada iteración.

Terminación: El bucle termina cuando se cumple la condición de salida (en while) o cuando se recorren todos los elementos (en for). # Tipos de bucles en Python

for: Recorre una secuencia (lista, rango, string, etc.).

while: Repite mientras una condición sea verdadera.

break / continue: Palabras clave para controlar el flujo dentro de un bucle (break termina, continue salta a la siguiente iteración).

##Bucle for

Definición: Repite un bloque de código para cada elemento de una secuencia (lista, rango, cadena, tupla, etc.).

Características:

Se ejecuta un número determinado de veces (según la secuencia o rango). Muy útil para recorrer listas, strings o rangos numéricos. Tiene alcance limitado a la secuencia: no necesita condicional extra. Concepto fundamental: Iteración sobre elementos de una colección o rango de valores.

Anatomía de un Bucle for

# for variable_iteracion in secuencia:
#     Cuerpo del bucle: código que se ejecuta en cada iteración
#     La variable_iteracion toma el valor de cada elemento de la secuencia

En Python, los componentes clave de un bucle for son:

for: palabra clave que inicia el bucle.

variable_iteracion: la variable que toma el valor de cada elemento de la secuencia.

in: operador que conecta la variable con la secuencia.

secuencia: cualquier iterable (lista, tupla, rango, etc.) sobre el que se iterará.

y sangría: delimitan el cuerpo del bucle; todo el código indentado se ejecuta en cada iteración. # Proceso de Ejecución

numeros = [10, 20, 30]

for numero in numeros:
    resultado = numero * 2
    print(f"Número: {numero} - Doble: {resultado}")
## Número: 10 - Doble: 20
## Número: 20 - Doble: 40
## Número: 30 - Doble: 60
# Iteración 1: numero = 10, resultado = 20, imprime "Número: 10 - Doble: 20"
    # Iteración 2: numero = 20, resultado = 40, imprime "Número: 20 - Doble: 40"
    # Iteración 3: numero = 30, resultado = 60, imprime "Número: 30 - Doble: 60"
# Fin del bucle

Tipos de Secuencias para Iterar

1. Secuencias Numéricas

print("=== SECUENCIAS NUMÉRICAS BÁSICAS ===\n")
## === SECUENCIAS NUMÉRICAS BÁSICAS ===
# Secuencia ascendente
print("Conteo del 1 al 5:\n")
## Conteo del 1 al 5:
print("=== SECUENCIAS NUMÉRICAS BÁSICAS ===\n")
## === SECUENCIAS NUMÉRICAS BÁSICAS ===
print("Conteo del 1 al 5:")
## Conteo del 1 al 5:
for i in range(1, 6):  # range es exclusivo del último valor
    print(f"Número: {i}")
## Número: 1
## Número: 2
## Número: 3
## Número: 4
## Número: 5
print("\nConteo descendente del 5 al 1:")
## 
## Conteo descendente del 5 al 1:
for i in range(5, 0, -1):  # tercer parámetro es el paso negativo
    print(f"Número: {i}")
## Número: 5
## Número: 4
## Número: 3
## Número: 2
## Número: 1
# Secuencia descendente
print("\nConteo descendente del 5 al 1:\n")
## 
## Conteo descendente del 5 al 1:
# Usando seq() para mayor control
print("\nNúmeros pares del 2 al 10:\n")
## 
## Números pares del 2 al 10:
for i in range(2, 11, 2):  # inicio=2, fin_exclusivo=11, paso=2
    print(f"Número par: {i}")
## Número par: 2
## Número par: 4
## Número par: 6
## Número par: 8
## Número par: 10
# Secuencia con decimales
print("\nSecuencia decimal:\n")
## 
## Secuencia decimal:
import numpy as np

for valor in np.arange(0.5, 2.6, 0.5):  # 2.6 para incluir 2.5
    print(f"Valor: {valor:.1f}")
## Valor: 0.5
## Valor: 1.0
## Valor: 1.5
## Valor: 2.0
## Valor: 2.5

2. Vectores de Caracteres

# Iterando sobre texto
print("\n=== PROCESAMIENTO DE TEXTO ===\n")
## 
## === PROCESAMIENTO DE TEXTO ===
# Vector de nombres
estudiantes = ["Ana María", "Pedro José", "Lucía Carmen", "Miguel Ángel"]

print("Lista de estudiantes:")
## Lista de estudiantes:
for nombre in estudiantes:
    print(nombre)
## Ana María
## Pedro José
## Lucía Carmen
## Miguel Ángel
estudiantes = ["Ana", "Pedro", "Luis", "María", "Carlos", "Sofia", "Diego", "Laura"]

for nombre in estudiantes:
    # Contar número de palabras
    num_palabras = len(nombre.split())
    # Contar número de caracteres
    num_caracteres = len(nombre)
    print(f"- {nombre}: {num_palabras} palabras, {num_caracteres} caracteres")
## - Ana: 1 palabras, 3 caracteres
## - Pedro: 1 palabras, 5 caracteres
## - Luis: 1 palabras, 4 caracteres
## - María: 1 palabras, 5 caracteres
## - Carlos: 1 palabras, 6 caracteres
## - Sofia: 1 palabras, 5 caracteres
## - Diego: 1 palabras, 5 caracteres
## - Laura: 1 palabras, 5 caracteres
# Días de la semana con información
dias_semana = ["Lunes", "Martes", "Miércoles", "Jueves", "Viernes", "Sábado", "Domingo"]
tipos_dia = ["Laboral", "Laboral", "Laboral", "Laboral", "Laboral", "Fin de semana", "Fin de semana"]

print("\nCalendario semanal:")
## 
## Calendario semanal:
for dia, tipo in zip(dias_semana, tipos_dia):
    print(f"{dia}: {tipo}")
## Lunes: Laboral
## Martes: Laboral
## Miércoles: Laboral
## Jueves: Laboral
## Viernes: Laboral
## Sábado: Fin de semana
## Domingo: Fin de semana
for i in range(len(dias_semana)):
    dia = dias_semana[i]
    tipo = tipos_dia[i]
    emoji = "maletin" if tipo == "Laboral" else "fiesta"
    print(f"{emoji} {dia} - {tipo}")
## maletin Lunes - Laboral
## maletin Martes - Laboral
## maletin Miércoles - Laboral
## maletin Jueves - Laboral
## maletin Viernes - Laboral
## fiesta Sábado - Fin de semana
## fiesta Domingo - Fin de semana

3. Listas Complejas

# Trabajando con estructuras de datos complejas
print("\n=== PROCESAMIENTO DE LISTAS ===\n")
## 
## === PROCESAMIENTO DE LISTAS ===
# Lista de información de empleados en Python

empleados = [
    {
        "nombre": "Carlos Mendoza",
        "departamento": "Ventas",
        "salario": 45000,
        "años_experiencia": 3,
        "certificaciones": ["Ventas Avanzadas", "CRM"]
    },
    {
        "nombre": "María González",
        "departamento": "IT",
        "salario": 65000,
        "años_experiencia": 7,
        "certificaciones": ["Java", "Python", "Scrum Master"]
    },
    {
        "nombre": "Roberto Silva",
        "departamento": "Marketing",
        "salario": 50000,
        "años_experiencia": 5,
        "certificaciones": ["Google Ads", "Analytics", "SEO"]
    }
]

print("=== REPORTE DE EMPLEADOS ===")
## === REPORTE DE EMPLEADOS ===
empleados = [
    {
        "nombre": "Carlos Mendoza",
        "departamento": "Ventas",
        "salario": 45000,
        "años_experiencia": 3,
        "certificaciones": ["Ventas Avanzadas", "CRM"]
    },
    {
        "nombre": "María González",
        "departamento": "IT",
        "salario": 65000,
        "años_experiencia": 7,
        "certificaciones": ["Java", "Python", "Scrum Master"]
    },
    {
        "nombre": "Roberto Silva",
        "departamento": "Marketing",
        "salario": 50000,
        "años_experiencia": 5,
        "certificaciones": ["Google Ads", "Analytics", "SEO"]
    }
]

print("=== REPORTE DE EMPLEADOS ===")
## === REPORTE DE EMPLEADOS ===
for i, emp in enumerate(empleados, start=1):
    # Calcular información derivada
    salario_mensual = emp["salario"] / 12
    
    if emp["años_experiencia"] >= 5:
        nivel_experiencia = "Senior"
    elif emp["años_experiencia"] >= 2:
        nivel_experiencia = "Intermedio"
    else:
        nivel_experiencia = "Junior"
    
    print(f"\n--- EMPLEADO {i} ---")
    print(f"Nombre: {emp['nombre']}")
    print(f"Departamento: {emp['departamento']}")
    print(f"Salario anual: ${emp['salario']:,}")
    print(f"Salario mensual: ${round(salario_mensual):,}")
    print(f"Experiencia: {emp['años_experiencia']} años ({nivel_experiencia})")
    print(f"Certificaciones ({len(emp['certificaciones'])}):")
    
    for cert in emp["certificaciones"]:
        print(f" • {cert}")
## 
## --- EMPLEADO 1 ---
## Nombre: Carlos Mendoza
## Departamento: Ventas
## Salario anual: $45,000
## Salario mensual: $3,750
## Experiencia: 3 años (Intermedio)
## Certificaciones (2):
##  • Ventas Avanzadas
##  • CRM
## 
## --- EMPLEADO 2 ---
## Nombre: María González
## Departamento: IT
## Salario anual: $65,000
## Salario mensual: $5,417
## Experiencia: 7 años (Senior)
## Certificaciones (3):
##  • Java
##  • Python
##  • Scrum Master
## 
## --- EMPLEADO 3 ---
## Nombre: Roberto Silva
## Departamento: Marketing
## Salario anual: $50,000
## Salario mensual: $4,167
## Experiencia: 5 años (Senior)
## Certificaciones (3):
##  • Google Ads
##  • Analytics
##  • SEO

Procesamiento de Datos Financieros

# Sistema de análisis financiero
print("\n=== ANÁLISIS FINANCIERO TRIMESTRAL ===\n")
## 
## === ANÁLISIS FINANCIERO TRIMESTRAL ===
# Datos de ventas por trimestre
meses = [
    "Enero", "Febrero", "Marzo", "Abril", "Mayo", "Junio",
    "Julio", "Agosto", "Septiembre", "Octubre", "Noviembre", "Diciembre"
]

ventas_2024 = [
    125000, 138000, 142000, 156000, 149000, 163000,
    178000, 171000, 165000, 183000, 195000, 210000
]

# Metas mensuales progresivas
metas = [
    120000, 125000, 130000, 135000, 140000, 145000,
    150000, 155000, 160000, 165000, 170000, 175000
]

# Variables para análisis
total_ventas = 0
total_metas = 0
meses_exitosos = 0
mejor_mes = ""
mejor_rendimiento = 0

print("REPORTE MENSUAL DETALLADO:")
## REPORTE MENSUAL DETALLADO:
print(f"{'Mes':<12}{'Ventas':>12}{'Meta':>12}{'Diferencia':>12}{'% Meta':>10}{'Estado':>10}")
## Mes               Ventas        Meta  Diferencia    % Meta    Estado
print("-" * 80)
## --------------------------------------------------------------------------------
for i in range(len(meses)):
    mes = meses[i]
    venta = ventas_2024[i]
    meta = metas[i]
    diferencia = venta - meta
    porcentaje_meta = (venta / meta) * 100

    # Actualizar totales
    total_ventas += venta
    total_metas += meta

    # Determinar estado
    if venta >= meta:
        meses_exitosos += 1
        estado = "ÉXITO"
    else:
        estado = "Bajo"

    # Buscar mejor rendimiento
    if porcentaje_meta > mejor_rendimiento:
        mejor_rendimiento = porcentaje_meta
        mejor_mes = mes

    # Formatear y mostrar resultados
    print(f"{mes:<12} "
          f"${venta:>10,} "
          f"${meta:>10,} "
          f"{diferencia:+10,} "
          f"{porcentaje_meta:9.1f}% "
          f"{estado}")
## Enero        $   125,000 $   120,000     +5,000     104.2% ÉXITO
## Febrero      $   138,000 $   125,000    +13,000     110.4% ÉXITO
## Marzo        $   142,000 $   130,000    +12,000     109.2% ÉXITO
## Abril        $   156,000 $   135,000    +21,000     115.6% ÉXITO
## Mayo         $   149,000 $   140,000     +9,000     106.4% ÉXITO
## Junio        $   163,000 $   145,000    +18,000     112.4% ÉXITO
## Julio        $   178,000 $   150,000    +28,000     118.7% ÉXITO
## Agosto       $   171,000 $   155,000    +16,000     110.3% ÉXITO
## Septiembre   $   165,000 $   160,000     +5,000     103.1% ÉXITO
## Octubre      $   183,000 $   165,000    +18,000     110.9% ÉXITO
## Noviembre    $   195,000 $   170,000    +25,000     114.7% ÉXITO
## Diciembre    $   210,000 $   175,000    +35,000     120.0% ÉXITO
print("-" * 80)
## --------------------------------------------------------------------------------
porcentaje_anual = (total_ventas / total_metas) * 100
superavit_total = total_ventas - total_metas

print(f"{'TOTAL AÑO':<12} "
      f"${total_ventas:>10,} "
      f"${total_metas:>10,} "
      f"{superavit_total:+10,} "
      f"{porcentaje_anual:9.1f}%")
## TOTAL AÑO    $ 1,975,000 $ 1,770,000   +205,000     111.6%
print("\n=== RESUMEN EJECUTIVO ===")
## 
## === RESUMEN EJECUTIVO ===
# Total vendido
print(f" Total vendido: ${total_ventas:,}")
##  Total vendido: $1,975,000
# Total de metas
print(f" Total de metas: ${total_metas:,}")
##  Total de metas: $1,770,000
# Rendimiento anual
print(f" Rendimiento anual: {porcentaje_anual:.1f}%")
##  Rendimiento anual: 111.6%
# Meses exitosos
print(f" Meses exitosos: {meses_exitosos} de {len(meses)}")
##  Meses exitosos: 12 de 12
# Mejor mes
print(f" Mejor mes: {mejor_mes} ({mejor_rendimiento:.1f}% de la meta)")
##  Mejor mes: Diciembre (120.0% de la meta)
if porcentaje_anual >= 100:
    print(" ¡Felicitaciones! Se superaron las metas anuales")
else:
    deficit = total_metas - total_ventas
    print(f" Área de mejora: ${deficit:,} por debajo de la meta")
##  ¡Felicitaciones! Se superaron las metas anuales

Sistema de Gestión Académica

# Procesamiento de calificaciones estudiantiles
print("\n=== SISTEMA DE GESTIÓN ACADÉMICA ===\n")
## 
## === SISTEMA DE GESTIÓN ACADÉMICA ===
# Base de datos de estudiantes
estudiantes_db = [
    {
        "nombre": "Ana Rodríguez",
        "id": "EST001",
        "materias": {
            "Matemáticas": {"parcial1": 85, "parcial2": 88, "final": 92, "asistencia": 95},
            "Física": {"parcial1": 78, "parcial2": 82, "final": 85, "asistencia": 90},
            "Química": {"parcial1": 90, "parcial2": 87, "final": 94, "asistencia": 98},
        },
    },
    {
        "nombre": "Pedro Martínez",
        "id": "EST002",
        "materias": {
            "Matemáticas": {"parcial1": 75, "parcial2": 79, "final": 82, "asistencia": 88},
            "Física": {"parcial1": 82, "parcial2": 85, "final": 88, "asistencia": 92},
            "Química": {"parcial1": 77, "parcial2": 80, "final": 83, "asistencia": 85},
        },
    },
    {
        "nombre": "Lucía Fernández",
        "id": "EST003",
        "materias": {
            "Matemáticas": {"parcial1": 92, "parcial2": 94, "final": 96, "asistencia": 100},
            "Física": {"parcial1": 88, "parcial2": 91, "final": 93, "asistencia": 95},
            "Química": {"parcial1": 95, "parcial2": 92, "final": 97, "asistencia": 98},
        },
    },
]

# Función para calcular nota final
def calcular_nota_final(parcial1, parcial2, final, asistencia):
    # 25% cada parcial, 40% examen final, 10% asistencia
    nota = (parcial1 * 0.25) + (parcial2 * 0.25) + (final * 0.40) + (asistencia * 0.10)
    return round(nota, 2)

# Función para determinar letra y estado
def obtener_calificacion(nota):
    if nota >= 90:
        return {"letra": "A", "estado": "Excelente", "puntos": 4.0}
    elif nota >= 80:
        return {"letra": "B", "estado": "Bueno", "puntos": 3.0}
    elif nota >= 70:
        return {"letra": "C", "estado": "Satisfactorio", "puntos": 2.0}
    elif nota >= 60:
        return {"letra": "D", "estado": "Mínimo", "puntos": 1.0}
    else:
        return {"letra": "F", "estado": "Reprobado", "puntos": 0.0}

# Procesar todos los estudiantes
print("REPORTE ACADÉMICO DETALLADO")
## REPORTE ACADÉMICO DETALLADO
print("-" * 60)
## ------------------------------------------------------------
for estudiante in estudiantes_db:
    print(f"\n ESTUDIANTE: {estudiante['nombre']} (ID: {estudiante['id']})")
    print("-" * 50)

    total_puntos = 0
    materias_cursadas = 0
    materias_aprobadas = 0

    # Procesar cada materia
    for materia_nombre, materia_data in estudiante["materias"].items():
        # Calcular nota final
        nota_final = calcular_nota_final(
            materia_data["parcial1"],
            materia_data["parcial2"],
            materia_data["final"],
            materia_data["asistencia"]
        )

        # Obtener calificación
        calificacion = obtener_calificacion(nota_final)

        # Actualizar contadores
        materias_cursadas += 1
        total_puntos += calificacion["puntos"]
        if calificacion["puntos"] > 0:
            materias_aprobadas += 1

        # Mostrar detalles de la materia
        print(f" {materia_nombre}:")
        print(f" Parcial 1: {materia_data['parcial1']} | "
              f"Parcial 2: {materia_data['parcial2']} | "
              f"Final: {materia_data['final']} | "
              f"Asistencia: {materia_data['asistencia']}%")
        print(f" → Nota final: {nota_final:.2f} "
              f"({calificacion['letra']}) - {calificacion['estado']}")

        # Identificar áreas de mejora
        if nota_final < 80:
            if materia_data["asistencia"] < 90:
                print(" Recomendación: Mejorar asistencia")
            if (materia_data["final"] < materia_data["parcial1"] or
                materia_data["final"] < materia_data["parcial2"]):
                print(" Recomendación: Prepararse mejor para exámenes finales")

        print()  # Línea en blanco

    # Calcular GPA
    gpa = round(total_puntos / materias_cursadas, 2) if materias_cursadas > 0 else 0

    # Determinar estado académico
    if gpa >= 3.5:
        estado_academico = "Lista de Honor"
    elif gpa >= 3.0:
        estado_academico = "Buen Rendimiento"
    elif gpa >= 2.0:
        estado_academico = "Rendimiento Satisfactorio"
    else:
        estado_academico = "Necesita Mejora"

    # Resumen del estudiante
    print(" RESUMEN ACADÉMICO:")
    print(f" GPA: {gpa:.2f}/4.0")
    print(f" Materias cursadas: {materias_cursadas}")
    print(f" Materias aprobadas: {materias_aprobadas}")
    print(f" Tasa de aprobación: {(materias_aprobadas / materias_cursadas) * 100:.1f}%")
    print(f" Estado académico: {estado_academico}")
    print("=" * 60)
## 
##  ESTUDIANTE: Ana Rodríguez (ID: EST001)
## --------------------------------------------------
##  Matemáticas:
##  Parcial 1: 85 | Parcial 2: 88 | Final: 92 | Asistencia: 95%
##  → Nota final: 89.55 (B) - Bueno
## 
##  Física:
##  Parcial 1: 78 | Parcial 2: 82 | Final: 85 | Asistencia: 90%
##  → Nota final: 83.00 (B) - Bueno
## 
##  Química:
##  Parcial 1: 90 | Parcial 2: 87 | Final: 94 | Asistencia: 98%
##  → Nota final: 91.65 (A) - Excelente
## 
##  RESUMEN ACADÉMICO:
##  GPA: 3.33/4.0
##  Materias cursadas: 3
##  Materias aprobadas: 3
##  Tasa de aprobación: 100.0%
##  Estado académico: Buen Rendimiento
## ============================================================
## 
##  ESTUDIANTE: Pedro Martínez (ID: EST002)
## --------------------------------------------------
##  Matemáticas:
##  Parcial 1: 75 | Parcial 2: 79 | Final: 82 | Asistencia: 88%
##  → Nota final: 80.10 (B) - Bueno
## 
##  Física:
##  Parcial 1: 82 | Parcial 2: 85 | Final: 88 | Asistencia: 92%
##  → Nota final: 86.15 (B) - Bueno
## 
##  Química:
##  Parcial 1: 77 | Parcial 2: 80 | Final: 83 | Asistencia: 85%
##  → Nota final: 80.95 (B) - Bueno
## 
##  RESUMEN ACADÉMICO:
##  GPA: 3.00/4.0
##  Materias cursadas: 3
##  Materias aprobadas: 3
##  Tasa de aprobación: 100.0%
##  Estado académico: Buen Rendimiento
## ============================================================
## 
##  ESTUDIANTE: Lucía Fernández (ID: EST003)
## --------------------------------------------------
##  Matemáticas:
##  Parcial 1: 92 | Parcial 2: 94 | Final: 96 | Asistencia: 100%
##  → Nota final: 94.90 (A) - Excelente
## 
##  Física:
##  Parcial 1: 88 | Parcial 2: 91 | Final: 93 | Asistencia: 95%
##  → Nota final: 91.45 (A) - Excelente
## 
##  Química:
##  Parcial 1: 95 | Parcial 2: 92 | Final: 97 | Asistencia: 98%
##  → Nota final: 95.35 (A) - Excelente
## 
##  RESUMEN ACADÉMICO:
##  GPA: 4.00/4.0
##  Materias cursadas: 3
##  Materias aprobadas: 3
##  Tasa de aprobación: 100.0%
##  Estado académico: Lista de Honor
## ============================================================

Simulación y Modelado

# Simulación de crecimiento poblacional
print("\n=== SIMULACIÓN DE CRECIMIENTO POBLACIONAL ===\n")
## 
## === SIMULACIÓN DE CRECIMIENTO POBLACIONAL ===
# Parámetros de simulación
poblacion_inicial = 10000
tasa_natalidad = 0.025   # 2.5% anual
tasa_mortalidad = 0.015  # 1.5% anual
tasa_migracion = 0.008   # 0.8% anual (inmigración neta)
años_simulacion = 20

# Variables para tracking
poblacion_actual = poblacion_inicial
historial_poblacion = [0] * (años_simulacion + 1)
historial_poblacion[0] = poblacion_inicial

print("SIMULACIÓN A 20 AÑOS:\n")
## SIMULACIÓN A 20 AÑOS:
for año in range(1, años_simulacion + 1):
    # Cambio poblacional = natalidad - mortalidad + migración
    cambio = poblacion_actual * (tasa_natalidad - tasa_mortalidad + tasa_migracion)
    poblacion_actual += cambio
    historial_poblacion[año] = int(poblacion_actual)  # guardamos como entero
    
    print(f"Año {año}: Población = {historial_poblacion[año]}")
## Año 1: Población = 10180
## Año 2: Población = 10363
## Año 3: Población = 10549
## Año 4: Población = 10739
## Año 5: Población = 10932
## Año 6: Población = 11129
## Año 7: Población = 11330
## Año 8: Población = 11534
## Año 9: Población = 11741
## Año 10: Población = 11953
## Año 11: Población = 12168
## Año 12: Población = 12387
## Año 13: Población = 12610
## Año 14: Población = 12837
## Año 15: Población = 13068
## Año 16: Población = 13303
## Año 17: Población = 13542
## Año 18: Población = 13786
## Año 19: Población = 14034
## Año 20: Población = 14287
print(f"Población inicial: {poblacion_inicial:,.0f} habitantes")
## Población inicial: 10,000 habitantes
print(f"Tasa de natalidad: {tasa_natalidad * 100:.1f}% anual")
## Tasa de natalidad: 2.5% anual
print(f"Tasa de mortalidad: {tasa_mortalidad * 100:.1f}% anual")
## Tasa de mortalidad: 1.5% anual
print(f"Migración neta: {tasa_migracion * 100:.1f}% anual\n")
## Migración neta: 0.8% anual
print(f"{'Año':<6} {'Población':>12} {'Nacim.':>8} {'Muertes':>8} {'Migrac.':>8} {'Crecimiento':>12}")
## Año       Población   Nacim.  Muertes  Migrac.  Crecimiento
print("-" * 65)
## -----------------------------------------------------------------
# Parámetros de simulación
poblacion_inicial = 10000
tasa_natalidad = 0.025
tasa_mortalidad = 0.015
tasa_migracion = 0.008
años_simulacion = 20

# Variables de seguimiento
poblacion_actual = poblacion_inicial
historial_poblacion = [0] * (años_simulacion + 1)
historial_poblacion[0] = poblacion_inicial

# Simulación
for año in range(1, años_simulacion + 1):
    # Calcular nacimientos, muertes y migración
    nacimientos = round(poblacion_actual * tasa_natalidad)
    muertes = round(poblacion_actual * tasa_mortalidad)
    migracion = round(poblacion_actual * tasa_migracion)
    
    # Guardar población anterior
    poblacion_anterior = poblacion_actual
    
    # Actualizar población
    poblacion_actual = poblacion_actual + nacimientos - muertes + migracion
    crecimiento_neto = poblacion_actual - poblacion_anterior
    
    # Guardar en historial
    historial_poblacion[año] = poblacion_actual
    
    # Mostrar resultados del año
    print(f"{año:<6d} {poblacion_actual:>12,} {nacimientos:>8,} {muertes:>8,} {migracion:>8,} {crecimiento_neto:+12,}")
    
    # Cada 5 años mostrar análisis de tendencia
    if año % 5 == 0:
        crecimiento_periodo = poblacion_actual - historial_poblacion[año - 5]
        tasa_crecimiento_periodo = ((poblacion_actual / historial_poblacion[año - 5]) ** (1/5) - 1) * 100
        print(f"  Crecimiento últimos 5 años: {crecimiento_periodo:,} ({tasa_crecimiento_periodo:.2f}% anual promedio)")
## 1            10,180      250      150       80         +180
## 2            10,362      254      153       81         +182
## 3            10,549      259      155       83         +187
## 4            10,739      264      158       84         +190
## 5            10,932      268      161       86         +193
##   Crecimiento últimos 5 años: 932 (1.80% anual promedio)
## 6            11,128      273      164       87         +196
## 7            11,328      278      167       89         +200
## 8            11,532      283      170       91         +204
## 9            11,739      288      173       92         +207
## 10           11,950      293      176       94         +211
##   Crecimiento últimos 5 años: 1,018 (1.80% anual promedio)
## 11           12,166      299      179       96         +216
## 12           12,385      304      182       97         +219
## 13           12,608      310      186       99         +223
## 14           12,835      315      189      101         +227
## 15           13,066      321      193      103         +231
##   Crecimiento últimos 5 años: 1,116 (1.80% anual promedio)
## 16           13,302      327      196      105         +236
## 17           13,541      333      200      106         +239
## 18           13,785      339      203      108         +244
## 19           14,033      345      207      110         +248
## 20           14,286      351      210      112         +253
##   Crecimiento últimos 5 años: 1,220 (1.80% anual promedio)
import math
# Análisis final
crecimiento_total = poblacion_actual - poblacion_inicial
tasa_crecimiento_anual_promedio = ((poblacion_actual / poblacion_inicial) ** (1 / años_simulacion) - 1) * 100
duplicacion_años = math.log(2) / math.log(1 + (tasa_crecimiento_anual_promedio / 100))

print("-" * 65)
## -----------------------------------------------------------------
print("\n ANÁLISIS FINAL DE LA SIMULACIÓN:\n")
## 
##  ANÁLISIS FINAL DE LA SIMULACIÓN:
print(f"Población final: {poblacion_actual:,} habitantes")
## Población final: 14,286 habitantes
print(f"Crecimiento total: {crecimiento_total:,} habitantes ({(crecimiento_total / poblacion_inicial) * 100:.1f}%)")
## Crecimiento total: 4,286 habitantes (42.9%)
print(f"Tasa de crecimiento anual promedio: {tasa_crecimiento_anual_promedio:.2f}%")
## Tasa de crecimiento anual promedio: 1.80%
print(f"Tiempo estimado para duplicar población: {duplicacion_años:.1f} años")
## Tiempo estimado para duplicar población: 38.9 años
# Proyección a 50 años (si la tasa es positiva)
if tasa_crecimiento_anual_promedio > 0:
    poblacion_en_50_años = poblacion_inicial * (1 + tasa_crecimiento_anual_promedio / 100) ** 50
    print(f"Proyección a 50 años: {round(poblacion_en_50_años):,} habitantes")
## Proyección a 50 años: 24,394 habitantes

Procesamiento Secuencial Dependiente

# Cálculos que dependen de iteraciones anteriores
print("\n=== ANÁLISIS DE SERIES TEMPORALES ===\n")
## 
## === ANÁLISIS DE SERIES TEMPORALES ===
# Datos de ventas mensuales
ventas_mensuales = [100000, 108000, 95000, 112000, 125000, 118000,
                    135000, 142000, 128000, 155000, 168000, 175000]

meses_nombres = ["Ene", "Feb", "Mar", "Abr", "May", "Jun",
                 "Jul", "Ago", "Sep", "Oct", "Nov", "Dic"]

# Variables para cálculos acumulativos (listas vacías con tamaño definido)
ventas_acumuladas = [0] * len(ventas_mensuales)
variacion_mensual = [0] * len(ventas_mensuales)
promedio_movil_3 = [0] * len(ventas_mensuales)

print("ANÁLISIS DE TENDENCIAS DE VENTAS:\n")
## ANÁLISIS DE TENDENCIAS DE VENTAS:
print(f"{'Mes':<4} {'Ventas':>10} {'Acumulado':>12} {'Variación':>10} {'Prom.Móvil':>12} {'Tendencia'}")
## Mes      Ventas    Acumulado  Variación   Prom.Móvil Tendencia
print("-" * 75)
## ---------------------------------------------------------------------------
for i in range(len(ventas_mensuales)):
    mes = meses_nombres[i]
    venta_actual = ventas_mensuales[i]

    # Ventas acumuladas
    if i == 0:
        ventas_acumuladas[i] = venta_actual
        variacion_mensual[i] = 0  # No hay mes anterior
    else:
        ventas_acumuladas[i] = ventas_acumuladas[i - 1] + venta_actual
        variacion_mensual[i] = ((venta_actual - ventas_mensuales[i - 1]) / ventas_mensuales[i - 1]) * 100

    # Promedio móvil de 3 meses
    if i >= 2:  # en Python, índices empiezan en 0
        promedio_movil_3[i] = sum(ventas_mensuales[i-2:i+1]) / 3
    else:
        promedio_movil_3[i] = None

    # Determinar tendencia
    if i == 0:
        tendencia = "Inicio"
    elif variacion_mensual[i] > 5:
        tendencia = "Alza fuerte"
    elif variacion_mensual[i] > 0:
        tendencia = "Crecimiento"
    elif variacion_mensual[i] > -5:
        tendencia = "Leve baja"
    else:
        tendencia = "Baja fuerte"

    # Formateo de valores
    variacion_str = " - " if i == 0 else f"{variacion_mensual[i]:+.1f}%"
    promedio_str = " - " if promedio_movil_3[i] is None else f"{promedio_movil_3[i]:8.0f}"

    # Mostrar resultados en tabla
    print(f"{mes:<4} {venta_actual:>10,} {ventas_acumuladas[i]:>12,} {variacion_str:>10} {promedio_str:>12} {tendencia}")
## Ene     100,000      100,000         -            -  Inicio
## Feb     108,000      208,000      +8.0%           -  Alza fuerte
## Mar      95,000      303,000     -12.0%       101000 Baja fuerte
## Abr     112,000      415,000     +17.9%       105000 Alza fuerte
## May     125,000      540,000     +11.6%       110667 Alza fuerte
## Jun     118,000      658,000      -5.6%       118333 Baja fuerte
## Jul     135,000      793,000     +14.4%       126000 Alza fuerte
## Ago     142,000      935,000      +5.2%       131667 Alza fuerte
## Sep     128,000    1,063,000      -9.9%       135000 Baja fuerte
## Oct     155,000    1,218,000     +21.1%       141667 Alza fuerte
## Nov     168,000    1,386,000      +8.4%       150333 Alza fuerte
## Dic     175,000    1,561,000      +4.2%       166000 Crecimiento
print("-" * 75)
## ---------------------------------------------------------------------------
# Cálculos de resumen
crecimiento_anual = ((ventas_mensuales[11] - ventas_mensuales[0]) / ventas_mensuales[0]) * 100
promedio_mensual = sum(ventas_mensuales) / len(ventas_mensuales)
mejor_mes_idx = ventas_mensuales.index(max(ventas_mensuales))  # posición del mejor mes
peor_mes_idx = ventas_mensuales.index(min(ventas_mensuales))  # posición del peor mes

print("\n RESUMEN ANUAL:\n")
## 
##  RESUMEN ANUAL:
print(f"Ventas totales: ${sum(ventas_mensuales):,}")
## Ventas totales: $1,561,000
print(f"Promedio mensual: ${round(promedio_mensual):,}")
## Promedio mensual: $130,083
print(f"Crecimiento anual: {crecimiento_anual:.1f}%")
## Crecimiento anual: 75.0%
print(f"Mejor mes: {meses_nombres[mejor_mes_idx]} (${ventas_mensuales[mejor_mes_idx]:,})")
## Mejor mes: Dic ($175,000)
print(f"Peor mes: {meses_nombres[peor_mes_idx]} (${ventas_mensuales[peor_mes_idx]:,})")
## Peor mes: Mar ($95,000)

Bucles while

Los bucles while representan una estructura de control fundamental que se ejecuta mientras una condición específica permanezca verdadera. A diferencia de los bucles for, que iteran sobre secuencias predefinidas, los bucles while continúan ejecutándose hasta que una condición cambie, lo que los hace ideales para situaciones donde no sabemos exactamente cuántas iteraciones necesitaremos. # Bucles while Un bucle while evalúa una condición antes de cada iteración. Si la condición es TRUE, ejecuta el bloque de código; si es FALSE, termina el bucle y continúa con la siguiente instrucción del programa. # Características fundamentales: • Evaluación previa: La condición se verifica antes de cada iteración • Flexibilidad: El número de iteraciones puede variar según los datos • Control dinámico: La condición puede cambiar durante la ejecución • Riesgo de bucles infinitos: Si la condición nunca se vuelve falsa # Anatomia de bucles while

# Definir la condición inicial
condicion = True

# Bucle while
while condicion:
    # Cuerpo del bucle
    # Código que se ejecuta mientras la condición sea True
    print("Ejecutando el bucle")

    # IMPORTANTE: debe haber algo que eventualmente cambie la condición
    # Aquí cambiamos la condición para salir después de una iteración
    condicion = False
## Ejecutando el bucle

Componentes esenciales:

while → palabra clave que inicia el bucle.

Condición → expresión lógica que se evalúa en cada iteración (True → se ejecuta, False → se detiene).

Cuerpo del bucle → bloque de instrucciones que se repite mientras la condición sea verdadera.

Actualización → cambio en las variables que afectan la condición (evita bucles infinitos).

Proceso de Ejecución

#Ejemplo paso a paso
contador = 1
while contador <= 3:
    print(f"Iteración: {contador}")
    contador += 1 
## Iteración: 1
## Iteración: 2
## Iteración: 3
# Evaluación 1: contador(1) <= 3 → TRUE → ejecutar cuerpo → contador = 2
# Evaluación 2: contador(2) <= 3 → TRUE → ejecutar cuerpo → contador = 3
# Evaluación 3: contador(3) <= 3 → TRUE → ejecutar cuerpo → contador = 4
# Evaluación 4: contador(4) <= 3 → FALSE → terminar bucle

Contadores y Acumuladores

# Sistema de contador simple
print("=== CONTADOR BÁSICO ===\n")
## === CONTADOR BÁSICO ===
numero = 1
suma_total = 0
print("Sumando números del 1 al 5:")
## Sumando números del 1 al 5:
while numero <= 5:
    suma_total += numero
    print(f"Sumando {numero}: total = {suma_total}")
    numero += 1
## Sumando 1: total = 1
## Sumando 2: total = 3
## Sumando 3: total = 6
## Sumando 4: total = 10
## Sumando 5: total = 15
print(f"Suma final: {suma_total}")
## Suma final: 15
# Contador con condición más compleja
print("\n=== SUMA HASTA LÍMITE ===\n")
## 
## === SUMA HASTA LÍMITE ===
suma = 0
contador = 1
limite = 100

print(f"Sumando números hasta que la suma supere {limite}:")
## Sumando números hasta que la suma supere 100:
while suma <= limite:
    suma = suma + contador
    print(f"Suma = {suma} (agregando {contador})")
    contador = contador + 1
## Suma = 1 (agregando 1)
## Suma = 3 (agregando 2)
## Suma = 6 (agregando 3)
## Suma = 10 (agregando 4)
## Suma = 15 (agregando 5)
## Suma = 21 (agregando 6)
## Suma = 28 (agregando 7)
## Suma = 36 (agregando 8)
## Suma = 45 (agregando 9)
## Suma = 55 (agregando 10)
## Suma = 66 (agregando 11)
## Suma = 78 (agregando 12)
## Suma = 91 (agregando 13)
## Suma = 105 (agregando 14)
print(f"Se necesitaron {contador - 1} números para superar {limite}")
## Se necesitaron 14 números para superar 100

Búsqueda y Validación

# Sistema de búsqueda secuencial
print("\n=== BÚSQUEDA EN LISTA ===\n")
## 
## === BÚSQUEDA EN LISTA ===
productos = ["Laptop", "Mouse", "Teclado", "Monitor", "Auriculares"]
producto_buscado = "Monitor"
indice = 1
encontrado = False

print(f"Buscando '{producto_buscado}' en la lista:")
## Buscando 'Monitor' en la lista:
productos = ["Laptop", "Mouse", "Teclado", "Monitor", "Auriculares"]
producto_buscado = "Monitor"
indice = 1
encontrado = False

while indice <= len(productos) and not encontrado:
    producto_actual = productos[indice - 1]  # En Python los índices empiezan en 0
    print(f"Revisando posición {indice}: {producto_actual}")

    if producto_actual == producto_buscado:
        encontrado = True
        print(f"¡Encontrado! '{producto_buscado}' está en la posición {indice}")
    else:
        indice += 1
## Revisando posición 1: Laptop
## Revisando posición 2: Mouse
## Revisando posición 3: Teclado
## Revisando posición 4: Monitor
## ¡Encontrado! 'Monitor' está en la posición 4
if not encontrado:
    print(f"'{producto_buscado}' no se encontró en la lista")

# Validación de entrada con bucle while
print("\n=== VALIDACIÓN DE ENTRADA ===\n")
## 
## === VALIDACIÓN DE ENTRADA ===
entradas_simuladas = ["abc", "-5", "150", "25"]  # Simular entradas del usuario
indice_entrada = 0  # En Python, índices empiezan en 0
edad_valida = False
edad = None

print("Solicitando edad válida (18-100 años):")
## Solicitando edad válida (18-100 años):
while not edad_valida and indice_entrada < len(entradas_simuladas):
    entrada = entradas_simuladas[indice_entrada]
    print(f"Entrada del usuario: '{entrada}'")

    try:
        edad_convertida = float(entrada)  # Intentar convertir
        if edad_convertida < 18:
            print("Error: Debe ser mayor de 18 años")
        elif edad_convertida > 100:
            print("Error: Edad no puede ser mayor a 100 años")
        else:
            edad = int(edad_convertida)
            edad_valida = True
            print(f"Edad válida aceptada: {edad} años")
    except ValueError:
        print("Error: Debe ingresar un número válido")

    indice_entrada += 1
## Entrada del usuario: 'abc'
## Error: Debe ingresar un número válido
## Entrada del usuario: '-5'
## Error: Debe ser mayor de 18 años
## Entrada del usuario: '150'
## Error: Edad no puede ser mayor a 100 años
## Entrada del usuario: '25'
## Edad válida aceptada: 25 años

if not edad_valida:
    print("No se pudo obtener una edad válida después de varios intentos")
if not edad_valida:
    print("No se pudo obtener una edad válida después de varios intentos")

While True

crea un bucle infinito, equivalente a repeat en R.

#Estructura Básica

condicion_de_salida = False  
contador = 1  # ejemplo de variable para controlar el bucle

while True:
    print(f"Iteración {contador}")
    
    # Aquí defines la condición real de salida
    if contador >= 3:  # esta es tu "alguna_condición"
        condicion_de_salida = True
    
    if condicion_de_salida:
        break
    
    contador += 1  # actualizar variable para que eventualmente se cumpla la condición
## Iteración 1
## Iteración 2
## Iteración 3

Características Clave

Ejecución garantizada al menos una vez

Al usar while True, el cuerpo del bucle se ejecuta inmediatamente.

Similar al repeat de R, no hay evaluación de condición antes de la primera ejecución.

Terminación manual con break

Python no evalúa automáticamente una condición de salida.

Debes usar if condición: break para salir del bucle.

Flexibilidad para múltiples condiciones de salida

Puedes tener varias evaluaciones dentro del bucle, usando if … break en diferentes puntos.

Esto permite terminar el bucle bajo distintas circunstancias, algo que en R también es posible con repeat.

Control total sobre la iteración

Puedes actualizar variables dentro del bucle sin restricciones.

Permite operaciones complejas antes de decidir si se rompe el bucle.

Posible riesgo de bucle infinito

Si nunca se cumple ninguna condición de salida y no hay break, el bucle seguirá ejecutándose indefinidamente.

Es importante siempre garantizar que alguna condición terminará el bucle. # Ejemplo

contador = 1

while True:
    print(f"Iteración: {contador}")
    contador += 1

    if contador > 3:
        break
## Iteración: 1
## Iteración: 2
## Iteración: 3

Menús Interactivos

while True:
    print("1. Opción A\n2. Opción B\n3. Salir")
    
    # Simulación de entrada del usuario
    opcion = "3"  # reemplaza con input("Seleccione: ") para entrada real
    
    if opcion == "1":
        print("Ejecutando opción A")
    elif opcion == "2":
        print("Ejecutando opción B")
    elif opcion == "3":
        print("Saliendo...")
        break
    else:
        print("Opción inválida")
## 1. Opción A
## 2. Opción B
## 3. Salir
## Saliendo...

Procesamiento Hasta Condición

import random

suma = 0

while True:
    numero = random.randint(1, 10)  # número aleatorio entre 1 y 10
    suma += numero
    print(f"Sumando: {numero} | Total: {suma}")
    
    if suma >= 20:
        print("Meta alcanzada")
        break
## Sumando: 2 | Total: 2
## Sumando: 9 | Total: 11
## Sumando: 10 | Total: 21
## Meta alcanzada

Control de bucles

Declaraciones de Control

break - Terminar Bucle Termina inmediatamente el bucle más interno y continúa con la siguiente instrucción.

for i in range(1, 21):
    if i > 10 and i % 2 == 0:
        print(f"Primer par mayor que 10: {i}")
        break
## Primer par mayor que 10: 12

next - Saltar Iteración

Salta el resto de la iteración actual y continúa con la siguiente.

for i in range(1, 11):
    if i % 2 == 0:
        continue  # Saltar números pares
    print(f"Número impar: {i}")
## Número impar: 1
## Número impar: 3
## Número impar: 5
## Número impar: 7
## Número impar: 9

Bucles Anidados con Control

for i in range(1, 4):
    print(f"Fila {i}")
    for j in range(1, 4):
        if i == 2 and j == 2:
            print("Saltando elemento (2,2)")
            continue  # Solo salta esta iteración del bucle interno
        print(f" Columna {j}")
## Fila 1
##  Columna 1
##  Columna 2
##  Columna 3
## Fila 2
##  Columna 1
## Saltando elemento (2,2)
##  Columna 3
## Fila 3
##  Columna 1
##  Columna 2
##  Columna 3