Guía Maestra del Curso: La siguiente estrategia, es iniciar con un problema concreto y relevante para cada Ingeniería con el objeto de captar el interés y dar un “porqué” inmediato para aprender los conceptos de programación.
A continuación, se detalla el plan de trabajo para cada semana del curso.
El objetivo de esta semana es aprender a comunicarnos con el computador: cómo darle información (entrada), cómo pedirle que la guarde en “cajas” con nombre (variables) y cómo nos puede mostrar los resultados (salida).
Al comenzar la clase, presentaremos tres escenarios, uno para cada ingeniería. El reto para los estudiantes será pensar en cómo darían instrucciones precisas a un computador para resolverlos.
Situación de Interés en Ingeniería Agrícola 🌾: Un agricultor necesita saber cuántos kilogramos de semilla de maíz debe comprar para sembrar un lote rectangular. Conoce la densidad de siembra recomendada (kg por hectárea) y las dimensiones del lote (largo y ancho en metros).
Situación de Interés en Ingeniería Agroindustrial 🥭: En una planta de procesamiento de mango, se quiere calcular el rendimiento de un lote de fruta. Se necesita un programa simple que tome el peso inicial de los mangos antes de pelarlos y deshuesarlos, y el peso final de la pulpa obtenida, para expresar el rendimiento como un porcentaje.
Situación de Interés en Ingeniería Civil 🧱: Un ingeniero residente de obra necesita calcular rápidamente el volumen de concreto necesario para vaciar una losa de piso rectangular simple. Debe poder ingresar el largo, el ancho y el espesor de la losa para obtener el volumen en metros cúbicos.
Una vez planteados los problemas, se introducen los conceptos de la
semana (variables, input()
, print()
,
float()
) como las herramientas necesarias. A continuación,
se muestra cómo aplicarlas para resolver cada caso.
Paso a Paso del Código:
input
).input
).input
).float
).print
).Código de Ejemplo en Colab:
# --- CALCULADORA DE SEMILLAS PARA LOTE AGRÍCOLA ---
print("🌱 Bienvenido a la Calculadora de Semillas de Maíz")
# Paso 2, 3 y 4: Pedir los datos al usuario
largo_str = input("Ingrese el largo del lote (en metros): ")
ancho_str = input("Ingrese el ancho del lote (en metros): ")
densidad_str = input("Ingrese la densidad de siembra (en kg por hectárea): ")
# Paso 5: Convertir los textos a números decimales
largo_m = float(largo_str)
ancho_m = float(ancho_str)
densidad_kg_ha = float(densidad_str)
# Paso 6 y 7: Calcular el área y convertir a hectáreas
area_m2 = largo_m * ancho_m
area_ha = area_m2 / 10000
# Paso 8: Calcular la cantidad de semilla
semilla_total_kg = area_ha * densidad_kg_ha
# Paso 9: Mostrar el resultado
print("\n--- RESULTADO DEL CÁLCULO ---")
print(f"El área del lote es de {area_ha:.4f} hectáreas.")
print(f"Necesitará comprar {semilla_total_kg:.2f} kg de semilla de maíz.")
💡 Prompts Sugeridos para IA:
"¿Qué es una variable en Python y para qué sirve? Dame una analogía."
,
"¿Por qué la función input() siempre devuelve texto (string) y cómo puedo convertir ese texto en un número?"
"Escribe el esqueleto de un programa en Python que pida dos números, los multiplique y muestre el resultado."
"Necesito calcular la cantidad de semilla para un lote. Primero debo calcular el área en m² (largo * ancho) y luego convertirla a hectáreas. ¿Cómo convierto metros cuadrados a hectáreas en Python?"
"En mi código de Python, ¿cómo puedo hacer que un número decimal se muestre con solo dos decimales al usar la función print()?"
Paso a Paso del Código:
input
).input
).float
).(peso_final / peso_inicial) * 100
.Código de Ejemplo en Colab:
# --- CALCULADORA DE RENDIMIENTO AGROINDUSTRIAL ---
print("🥭 Bienvenido a la Calculadora de Rendimiento de Pulpa")
# Paso 2 y 3: Pedir los datos al usuario
peso_inicial_str = input("Ingrese el peso inicial del lote de mangos (en kg): ")
peso_final_str = input("Ingrese el peso final de la pulpa obtenida (en kg): ")
# Paso 4: Convertir a números
peso_inicial = float(peso_inicial_str)
peso_final = float(peso_final_str)
# Paso 5: Calcular el rendimiento
# Se añade una verificación para evitar división por cero
if peso_inicial > 0:
rendimiento_porcentaje = (peso_final / peso_inicial) * 100
# Paso 6: Mostrar el resultado
print("\n--- RESULTADO DEL ANÁLISIS ---")
print(f"El rendimiento del lote fue del {rendimiento_porcentaje:.2f}%.")
else:
print("Error: El peso inicial debe ser mayor que cero.")
💡 Prompts Sugeridos para IA:
"¿Qué son los operadores aritméticos en Python? Dame una lista."
,
"¿Por qué es importante verificar que no estoy dividiendo por cero en un programa?"
"Quiero crear un programa que calcule un porcentaje. Necesito pedir un valor total y un valor parcial. ¿Cómo estructuro el código en Python?"
"Tengo dos variables, 'peso_inicial' y 'peso_final'. Escribe la fórmula en Python para calcular el rendimiento porcentual."
Paso a Paso del Código:
input
).float
).Código de Ejemplo en Colab:
# --- CALCULADORA DE VOLUMEN DE CONCRETO PARA LOSA ---
print("🧱 Bienvenido a la Calculadora de Volumen de Concreto")
# Paso 2: Pedir las dimensiones
largo_str = input("Ingrese el largo de la losa (en metros): ")
ancho_str = input("Ingrese el ancho de la losa (en metros): ")
espesor_str = input("Ingrese el espesor de la losa (en metros): ")
# Paso 3: Convertir a números
largo = float(largo_str)
ancho = float(ancho_str)
espesor = float(espesor_str)
# Paso 4: Calcular el volumen
volumen_m3 = largo * ancho * espesor
# Paso 5: Mostrar el resultado
print("\n--- RESULTADO DEL CÁLCULO ---")
print(f"El volumen de concreto necesario es de {volumen_m3:.3f} metros cúbicos.")
💡 Prompts Sugeridos para IA:
"¿Python sigue el orden de las operaciones matemáticas (PEMDAS)? Dame un ejemplo."
"Necesito un programa que pida 3 números al usuario, los multiplique entre sí y muestre el resultado. ¿Puedes escribírmelo en Python?"
"Tengo 3 variables en Python: 'largo', 'ancho' y 'espesor'. ¿Cuál es la línea de código para calcular el 'volumen'?"
,
"¿Cómo puedo mostrar 'm³' en la salida de mi programa de Python?"
El objetivo de estas dos semanas es darles a nuestros programas la
capacidad de “pensar”. Aprenderemos las estructuras de control que les
permiten tomar decisiones basadas en condiciones
(if/elif/else
) y ejecutar tareas de forma repetitiva
(for
, while
), que es la base de toda
automatización.
Situación de Interés en Ingeniería Agrícola 💧: Se está diseñando el software para un sistema de riego “inteligente”. El programa debe leer el nivel de humedad actual del suelo (un valor de 0 a 100) y decidir qué acción tomar: no hacer nada, aplicar un riego ligero o aplicar un riego profundo, según umbrales predefinidos.
Situación de Interés en Ingeniería Agroindustrial 📦: En una línea de empaque de frutas, un sensor mide el peso de cada fruta. Se necesita un programa que analice una lista de pesos de un lote y cuente cuántas frutas cumplen con el estándar de “Exportación” (ej. > 250g), cuántas son de “Mercado Nacional” (entre 150g y 250g) y cuántas se consideran “Rechazo” (< 150g).
Situación de Interés en Ingeniería Civil 🔩: Durante el control de calidad en una obra, se deben realizar pruebas de resistencia a la compresión en múltiples muestras de concreto. Se requiere un programa que permita al usuario ingresar el resultado de cada prueba (en PSI) y verifique si cumple con el mínimo requerido por el diseño. El programa debe poder analizar una muestra tras otra, hasta que el usuario decida detenerse.
A continuación, se muestra cómo resolver cada escenario usando las estructuras de control de Python.
if/elif/else
)Paso a Paso del Código:
float
).if/elif/else
para comparar la
humedad con los umbrales.if
la humedad es muy alta, imprimir “Suelo saturado, no
regar”.elif
la humedad es muy baja, imprimir “Suelo seco,
aplicando riego profundo”.else
(para el caso intermedio), imprimir “Humedad
óptima, aplicando riego ligero de mantenimiento”.Código de Ejemplo en Colab:
# --- SOFTWARE PARA SISTEMA DE RIEGO INTELIGENTE ---
print("💧 Módulo de Decisión de Riego")
# Pedir el dato del sensor (simulado con input)
humedad_str = input("Ingrese el porcentaje de humedad del suelo (0-100): ")
humedad = float(humedad_str)
# Definir umbrales
UMBRAL_OPTIMO = 30
UMBRAL_SATURADO = 70
print("\n--- ANÁLISIS Y ACCIÓN ---")
# Estructura de decisión
if humedad > UMBRAL_SATURADO:
print(f"🔴 Acción: No regar. Humedad actual ({humedad}%) por encima del umbral de saturación.")
elif humedad < UMBRAL_OPTIMO:
print(f"🔵 Acción: Aplicar RIEGO PROFUNDO. Humedad actual ({humedad}%) por debajo del umbral óptimo.")
else: # Si no es ninguna de las anteriores, está en el rango óptimo
print(f"🟢 Acción: Aplicar RIEGO LIGERO. Humedad ({humedad}%) en niveles óptimos.")
💡 Prompts Sugeridos para IA:
"Explícame la diferencia entre 'if', 'elif' y 'else' en Python. ¿Puedo usar múltiples 'elif'?"
"Escribe un programa en Python que pida una calificación numérica y la convierta a una letra (A, B, C, F) usando condicionales."
"Necesito un código que haga una cosa si una variable 'x' es menor que 10, otra cosa si está entre 10 y 50, y una tercera cosa si es mayor que 50. ¿Cómo escribo esa estructura if/elif/else?"
for
loop)Paso a Paso del Código:
exportacion
,
nacional
y rechazo
.for
para recorrer cada peso
en la lista de pesos_lote
.if/elif/else
para clasificar
cada peso
.Código de Ejemplo en Colab:
# --- SISTEMA DE CLASIFICACIÓN DE FRUTAS POR PESO ---
print("📦 Analizador de Lote de Frutas")
# 1. Simulación de datos del sensor
pesos_lote = [260.5, 140.2, 180.9, 290.0, 310.1, 150.0, 250.1, 130.8, 200.0]
# 2. Inicializar contadores
contador_exportacion = 0
contador_nacional = 0
contador_rechazo = 0
# 3. Bucle 'for' para analizar cada fruta
for peso in pesos_lote:
# 4. Clasificación dentro del bucle
if peso > 250:
contador_exportacion += 1
elif peso >= 150: # No es necesario poner 'and peso <= 250' porque el primer 'if' ya lo descarta
contador_nacional += 1
else:
contador_rechazo += 1
# 6. Imprimir el resumen final
print("\n--- RESUMEN DEL LOTE ---")
print(f"Frutas de Exportación (>250g): \t{contador_exportacion} unidades")
print(f"Frutas de Mercado Nacional (150-250g): \t{contador_nacional} unidades")
print(f"Frutas de Rechazo (<150g): \t\t{contador_rechazo} unidades")
print("---------------------------------")
print(f"Total de frutas analizadas: \t{len(pesos_lote)} unidades")
💡 Prompts Sugeridos para IA:
"¿Qué es un bucle 'for' en Python y para qué se usa principalmente? Dame un ejemplo con una lista de nombres."
"Escribe un programa en Python que recorra una lista de números y cuente cuántos son pares y cuántos son impares."
"Tengo una lista de números llamada 'datos'. Quiero recorrerla con un bucle 'for'. Dentro del bucle, si el número es mayor a 100, quiero sumarle 1 a una variable llamada 'contador'. ¿Cómo escribo ese código?"
while
loop)Paso a Paso del Código:
while True:
. Este tipo de
bucle seguirá ejecutándose hasta que le demos una instrucción explícita
para detenerse (break
).break
para salir del bucle.float
) y
compararlo con la resistencia mínima.Código de Ejemplo en Colab:
# --- VERIFICADOR DE PRUEBAS DE RESISTENCIA DE CONCRETO ---
print("🔩 Verificador de Resistencia a la Compresión")
print("(Escribe 'salir' en cualquier momento para terminar)")
# 1. Resistencia mínima requerida por el diseño
RESISTENCIA_MINIMA_PSI = 3000
# 2. Bucle 'while' para analizar muestras continuamente
while True:
# 3. Pedir el resultado
resultado_str = input("\nIngrese el resultado de la prueba (en PSI): ")
# 4. Condición de salida
if resultado_str.lower() == "salir":
break # Detiene el bucle while
# 5. Convertir y evaluar
try:
resultado_psi = float(resultado_str)
if resultado_psi >= RESISTENCIA_MINIMA_PSI:
print(f"✅ Resultado: {resultado_psi} PSI. ¡CUMPLE con el estándar de {RESISTENCIA_MINIMA_PSI} PSI!")
else:
print(f"❌ Resultado: {resultado_psi} PSI. ¡NO CUMPLE! La muestra es rechazada.")
except ValueError:
print("Entrada no válida. Por favor, ingrese un número o la palabra 'salir'.")
# 7. Mensaje final
print("\n--- Proceso de verificación finalizado. ---")
💡 Prompts Sugeridos para IA:
"¿Cuál es la diferencia entre un bucle 'for' y un bucle 'while'? Dame un ejemplo donde sea mejor usar 'while'."
,
"¿Qué hace la palabra clave 'break' dentro de un bucle?"
"Escribe un programa que sea una calculadora simple (suma, resta). Debe permitir al usuario hacer múltiples cálculos hasta que decida salir. ¿Qué tipo de bucle debería usar?"
Continúamos con la planificación detallada para las Semanas 4 y 5, enfocadas en cómo organizar la información de manera eficiente y cómo crear bloques de código reutilizables.
El objetivo de estas semanas es dar un salto cualitativo en nuestra capacidad de programación. Dejaremos de trabajar con datos sueltos para aprender a agruparlos en colecciones estructuradas (Listas y Diccionarios). Además, aprenderemos a encapsular nuestra lógica en “recetas” reutilizables llamadas Funciones, lo que nos permitirá escribir código mucho más limpio, eficiente y fácil de entender.
Situación de Interés en Ingeniería Agrícola 🌱: Un agrónomo consultor necesita una herramienta rápida para aconsejar a los agricultores sobre qué cultivos sembrar. Se requiere un programa que almacene información de varios cultivos (nombre, mes ideal de siembra, necesidad de agua) y que, al ingresar el nombre de un mes, recomiende qué cultivos son adecuados para sembrar en ese período.
Situación de Interés en Ingeniería Agroindustrial 🏭: El jefe de bodega de una planta de alimentos necesita un sistema simple para gestionar el inventario de materia prima. El programa debe permitirle ver el stock actual, registrar la llegada de un nuevo lote de un producto (añadir al stock) y registrar el consumo de materia prima para la producción (restar del stock).
Situación de Interés en Ingeniería Civil ⚖️: Un ingeniero estructural necesita calcular el peso de diferentes elementos de una construcción (vigas, columnas). El programa debe tener una base de datos con las densidades de materiales comunes (acero, concreto, madera) y, a partir del tipo de material y el volumen del elemento, debe calcular su peso total.
A continuación, la aplicación de listas, diccionarios y funciones para resolver cada escenario.
Paso a Paso del Código:
nombre
, mes_siembra
y
riego
.recomendar_cultivos
. Esta función recibirá dos parámetros:
la lista completa de cultivos y el mes actual.for
para recorrer
la lista de cultivos.if
para comprobar si el
mes_siembra
del cultivo coincide con el mes
proporcionado.recomendados
.devolver
la lista de cultivos
recomendados.Código de Ejemplo en Colab:
# --- PLANIFICADOR INTELIGENTE DE CULTIVOS ---
# 1. Base de datos de cultivos (una lista de diccionarios)
DB_CULTIVOS = [
{"nombre": "Maíz", "mes_siembra": "Abril", "riego": "Alto"},
{"nombre": "Frijol", "mes_siembra": "Mayo", "riego": "Medio"},
{"nombre": "Tomate", "mes_siembra": "Abril", "riego": "Alto"},
{"nombre": "Yuca", "mes_siembra": "Septiembre", "riego": "Bajo"},
{"nombre": "Sorgo", "mes_siembra": "Mayo", "riego": "Bajo"}
]
# 2. Función para obtener recomendaciones
def recomendar_cultivos(catalogo, mes_actual):
"""Filtra el catálogo de cultivos y devuelve los recomendados para un mes."""
cultivos_recomendados = [] # 5. Inicia una lista vacía
for cultivo in catalogo: # 3. Recorre la base de datos
if cultivo["mes_siembra"].lower() == mes_actual.lower(): # 4. Compara
cultivos_recomendados.append(cultivo["nombre"]) # 5. Añade si coincide
return cultivos_recomendados # 6. Devuelve la lista final
# 7. Programa Principal
print("🌱 Bienvenido al Asistente de Siembra")
mes_usuario = input("Ingrese el mes actual (ej. Abril): ")
recomendaciones = recomendar_cultivos(DB_CULTIVOS, mes_usuario)
print("\n--- RECOMENDACIONES ---")
if recomendaciones: # Si la lista no está vacía
print(f"Para el mes de {mes_usuario}, se recomienda sembrar:")
for cultivo in recomendaciones:
print(f"- {cultivo}")
else:
print(f"No se encontraron cultivos ideales para sembrar en {mes_usuario}.")
💡 Prompts Sugeridos para IA:
"¿Qué es un diccionario en Python y cómo se diferencia de una lista?"
,
"Explícame el propósito de la palabra clave 'return' en una función de Python."
"Escribe una función en Python que reciba una lista de nombres y una letra, y devuelva una nueva lista solo con los nombres que empiezan con esa letra."
"Tengo una lista de diccionarios. Cada diccionario tiene una clave 'ciudad'. ¿Cómo escribo un bucle 'for' para imprimir solo el valor de la clave 'ciudad' de cada diccionario en la lista?"
Paso a Paso del Código:
agregar_stock
que
reciba el inventario, el nombre del ítem y la cantidad a añadir. La
función modificará el diccionario.usar_stock
que
reciba el inventario, el ítem y la cantidad a usar. Esta función debe
verificar si hay suficiente stock antes de restar.mostrar_inventario
que recorra el diccionario e imprima el stock de cada producto.while
para
mostrar un menú de opciones al usuario (ver, agregar, usar, salir) y
llamar a la función correspondiente según su elección.Código de Ejemplo en Colab:
# --- SISTEMA BÁSICO DE GESTIÓN DE INVENTARIO ---
# 1. El inventario es un diccionario
inventario = {"Harina (kg)": 500, "Azúcar (kg)": 250, "Sal (kg)": 100}
# 2. Función para añadir stock
def agregar_stock(inv, item, cantidad):
if item in inv:
inv[item] += cantidad
else:
inv[item] = cantidad
print(f"✅ Se agregaron {cantidad} a '{item}'. Nuevo total: {inv[item]}")
# 3. Función para usar stock
def usar_stock(inv, item, cantidad):
if item in inv and inv[item] >= cantidad:
inv[item] -= cantidad
print(f"✅ Se usaron {cantidad} de '{item}'. Quedan: {inv[item]}")
else:
print(f"❌ Error: No hay suficiente stock de '{item}' o el ítem no existe.")
# 4. Función para mostrar el inventario
def mostrar_inventario(inv):
print("\n--- INVENTARIO ACTUAL ---")
for item, cantidad in inv.items():
print(f"- {item}: {cantidad}")
print("-------------------------")
# 5. Programa principal con menú
while True:
mostrar_inventario(inventario)
opcion = input("\n¿Qué desea hacer? (1:Agregar, 2:Usar, 3:Salir): ")
if opcion == "1":
item = input("Nombre del ítem: ")
cantidad = float(input("Cantidad a agregar: "))
agregar_stock(inventario, item, cantidad)
elif opcion == "2":
item = input("Nombre del ítem: ")
cantidad = float(input("Cantidad a usar: "))
usar_stock(inventario, item, cantidad)
elif opcion == "3":
break
print("Programa finalizado.")
💡 Prompts Sugeridos para IA:
"¿Cómo puedo añadir un nuevo par clave-valor a un diccionario existente en Python?"
,
"En una función, ¿qué significa que un diccionario se pasa 'por referencia'?"
"Quiero hacer un menú simple en un programa de consola. El usuario debe poder elegir entre 3 opciones. ¿Qué estructura de bucle y condicionales me recomiendas?"
Paso a Paso del Código:
calcular_peso
que
reciba el diccionario de densidades, el nombre del material y su
volumen.devolver
el peso
(densidad * volumen). Si no, devolver un mensaje de error o
None
.calcular_peso
y mostrar el
resultado.Código de Ejemplo en Colab:
# --- CALCULADORA DE PESO DE ELEMENTOS ESTRUCTURALES ---
# 1. Base de datos de densidades (kg/m³)
DENSIDADES = {
"concreto": 2400,
"acero": 7850,
"madera": 700,
"aluminio": 2700
}
# 2. Función para el cálculo principal
def calcular_peso(db_densidades, material, volumen):
"""Busca la densidad de un material y calcula su peso dado un volumen."""
material = material.lower() # Convertir a minúsculas para evitar errores
if material in db_densidades:
densidad = db_densidades[material]
peso = densidad * volumen
return peso
else:
return None # Indica que el material no fue encontrado
# 5. Programa principal
print("⚖️ Bienvenido a la Calculadora de Peso Estructural")
material_usuario = input(f"Ingrese el material ({', '.join(DENSIDADES.keys())}): ")
volumen_usuario = float(input("Ingrese el volumen del elemento (en m³): "))
# 6. Llamar a la función y mostrar resultado
peso_calculado = calcular_peso(DENSIDADES, material_usuario, volumen_usuario)
print("\n--- RESULTADO ---")
if peso_calculado is not None:
print(f"Un elemento de {material_usuario} con un volumen de {volumen_usuario} m³ pesa aproximadamente {peso_calculado:.2f} kg.")
else:
print(f"Error: El material '{material_usuario}' no se encuentra en la base de datos.")
💡 Prompts Sugeridos para IA:
"¿Cómo puedo acceder al valor de un diccionario si tengo su clave en Python?"
,
"¿Qué pasa si intento acceder a una clave que no existe en un diccionario? ¿Cómo puedo evitar que mi programa falle por eso?"
"Escribe una función que reciba un diccionario y una clave como parámetros. La función debe devolver el valor asociado a esa clave. Si la clave no existe, debe devolver el mensaje 'No encontrado'."
Continuamos con el plan de estudio detallado para las Semanas 6 y 7, un bloque fundamental para que los estudiantes aprendan a crear programas robustos y a gestionar su trabajo como profesionales.
En estas semanas, nos enfocaremos en dos aspectos cruciales de la
programación profesional. Primero, aprenderemos a anticipar y gestionar
errores con try...except
, para que
nuestros programas no “crasheen” o se detengan inesperadamente ante una
entrada inválida del usuario. Segundo, introduciremos conceptualmente el
porqué de Git y GitHub, el sistema estándar en la
industria para guardar “fotografías” de nuestro progreso y colaborar en
equipo.
Situación de Interés en Ingeniería Agrícola sprayer️: Un operador de campo necesita una herramienta en su tablet para calcular la tasa de aplicación de un agroquímico. El programa debe pedirle el área a tratar y el volumen total de mezcla. El problema: ¿Qué pasa si el operador, por error, escribe “doscientos” en lugar de “200” o ingresa un área de 0? El programa debe ser lo suficientemente robusto para manejar estos errores sin cerrarse. El contexto Git: Una vez que el programa funcione, ¿cómo guardamos esta versión estable antes de añadirle nuevas funciones, como un conversor de unidades?
Situación de Interés en Ingeniería Agroindustrial 🌡️: Se requiere un programa para estimar las necesidades energéticas de un proceso de calentamiento. El programa pide la masa del producto a calentar y el cambio de temperatura deseado. El problema: El usuario podría ingresar valores negativos o texto. El programa debe validar que las entradas sean números positivos y lógicos para el cálculo. El contexto Git: Desarrollas una primera versión. ¿Cómo podrías compartir tu código con un colega de ingeniería mecánica para que él añada los cálculos de eficiencia del intercambiador de calor, trabajando ambos en el mismo proyecto sin pisarse el trabajo?
Situación de Interés en Ingeniería Civil 📉: Un estudiante de geotecnia está creando un script para calcular el factor de seguridad de un talud simple. El programa pide la cohesión del suelo, el ángulo de fricción y el peso del material. El problema: Los cálculos matemáticos (como la tangente de 90 grados) pueden generar errores. Además, el usuario puede ingresar datos no numéricos. El programa debe “atrapar” estos errores y guiar al usuario para que corrija la entrada. El contexto Git: ¿Cómo mantienes un historial de todas las versiones de tu modelo de cálculo, para poder volver a una versión anterior si descubres que un cambio nuevo introdujo un error?
A continuación, la solución a cada escenario, centrada en el manejo de errores.
try...except
)Paso a Paso del Código:
while
para permitir múltiples
cálculos.try:
.float
. Si el usuario ingresa
texto, esto generará un ValueError
.ZeroDivisionError
.except
:
except ValueError:
para atrapar errores de conversión
de texto a número.except ZeroDivisionError:
para atrapar el error de
división por cero.except Exception as e:
como una red de seguridad para
cualquier otro error inesperado.while
.Código de Ejemplo en Colab:
# --- CALCULADORA ROBUSTA DE DOSIS DE AGROQUÍMICOS ---
print(" sprayer️ Bienvenido a la Calculadora de Tasa de Aplicación")
while True:
try:
# 3 y 4. Petición y conversión de datos dentro del 'try'
area_ha = float(input("\nIngrese el área a tratar (en hectáreas): "))
volumen_l = float(input("Ingrese el volumen total de la mezcla (en litros): "))
# 5. Verificación para evitar división por cero
if area_ha <= 0:
print("❌ Error: El área debe ser un número positivo mayor que cero.")
continue # Vuelve al inicio del bucle
# 6. Cálculo
tasa_aplicacion = volumen_l / area_ha
# Mostrar resultado
print("\n--- RESULTADO ---")
print(f"La tasa de aplicación requerida es de {tasa_aplicacion:.2f} litros por hectárea.")
# 7. Manejo de errores específicos
except ValueError:
print("❌ Error: Por favor, ingrese únicamente valores numéricos.")
except ZeroDivisionError: # Este caso ya lo controlamos con el 'if', pero es buena práctica tenerlo
print("❌ Error: El área no puede ser cero.")
except Exception as e:
print(f"Ocurrió un error inesperado: {e}")
# 8. Control del bucle
otro_calculo = input("\n¿Desea realizar otro cálculo? (s/n): ")
if otro_calculo.lower() != 's':
break # Sale del bucle
print("Programa finalizado.")
💡 Prompts Sugeridos para IA:
"Explícame qué es una 'excepción' en programación. ¿Por qué es mejor 'pedir perdón que pedir permiso' (usar try-except) en Python?"
"Escribe un esqueleto de código en Python que pida un número al usuario y lo use en un cálculo, pero que no falle si el usuario escribe texto en su lugar."
"Mi programa de división a veces se detiene con un error
ZeroDivisionError. ¿Cómo uso
try-exceptpara atrapar específicamente ese error y mostrar un mensaje personalizado?"
Paso a Paso del Código:
calcular_energia
que contenga la
lógica de cálculo y validación.try-except
para asegurar que
las entradas son numéricas.try
, usar un if
para validar
que los números sean lógicos (positivos). Si no lo son, se puede usar
raise ValueError("Mensaje de error")
para generar un error
intencionalmente que será atrapado por el except
.Código de Ejemplo en Colab:
# --- CALCULADORA DE NECESIDADES ENERGÉTICAS ---
# 1. Constante (ej: calor específico del agua en J/kg°C)
CALOR_ESPECIFICO = 4186
def calcular_energia_requerida(masa_kg, temp_inicial, temp_final):
"""Calcula la energía (en Joules) para calentar una masa. Valida las entradas."""
try:
# 3. Conversión a float
masa = float(masa_kg)
t_ini = float(temp_inicial)
t_fin = float(temp_final)
# 4. Validación lógica
if masa <= 0 or (t_fin <= t_ini):
raise ValueError("La masa debe ser positiva y la temperatura final mayor a la inicial.")
# 5. Cálculo Q = m * c * ΔT
delta_temp = t_fin - t_ini
energia_j = masa * CALOR_ESPECIFICO * delta_temp
return energia_j, None # Devuelve el resultado y ningún error
except ValueError as e:
return None, str(e) # Devuelve nada en el resultado y el mensaje de error
# Programa Principal
print("🌡️ Calculadora de Energía para Calentamiento de Productos")
m_str = input("Ingrese la masa del producto (kg): ")
ti_str = input("Ingrese la temperatura inicial (°C): ")
tf_str = input("Ingrese la temperatura final (°C): ")
energia, error = calcular_energia_requerida(m_str, ti_str, tf_str)
if error:
print(f"\n❌ Error en el cálculo: {error}")
else:
print(f"\n⚡ Energía requerida: {energia / 1000:.2f} kJ (kiloJoules)")
💡 Prompts Sugeridos para IA:
"¿Puedo tener múltiples bloques 'except' para un solo 'try'? ¿Cómo funciona?"
"Dentro de un bloque 'try', ¿cómo puedo verificar si un número es negativo y, si lo es, detener el cálculo y mostrar un mensaje de error personalizado?"
,
"Explícame qué hace 'raise ValueError' y en qué situación lo usaría."
Paso a Paso del Código:
math
para funciones
trigonométricas.try-except
muy amplio.try
, convertir las entradas a
float
.math.tan()
puede generar un error si el ángulo es de 90
grados, pero el try-except
general lo atrapará.except
, en lugar de diferenciar errores,
se puede mostrar un mensaje genérico indicando que los datos son
inválidos, guiando al usuario a revisar los números ingresados.Código de Ejemplo en Colab:
# --- VERIFICADOR SIMPLIFICADO DE FACTOR DE SEGURIDAD ---
import math
def calcular_fs_talud(cohesion, peso, angulo_friccion_grados):
"""Calcula un factor de seguridad simplificado. Atrapa cualquier error de cálculo."""
try:
# 4. Conversión a números
c = float(cohesion)
w = float(peso)
phi = float(angulo_friccion_grados)
# Validación lógica básica
if c < 0 or w <= 0 or not (0 <= phi < 90):
print("⚠️ Advertencia: Datos fuera de rango físico esperado.")
return # Sale de la función si los datos son ilógicos
# 5. Cálculo (puede generar errores matemáticos)
# Convertir ángulo a radianes para la función tan()
phi_rad = math.radians(phi)
fuerza_resistente = c + w * math.cos(phi_rad) * math.tan(phi_rad)
fuerza_actuante = w * math.sin(phi_rad)
fs = fuerza_resistente / fuerza_actuante
print(f"✅ Factor de Seguridad calculado: {fs:.3f}")
if fs > 1.5:
print("Interpretación: El talud se considera estable bajo estas condiciones.")
else:
print("Interpretación: Se requiere un análisis más detallado. Factor de seguridad bajo.")
# 6. Atrapa cualquier error (numérico, matemático, etc.)
except (ValueError, ZeroDivisionError):
print("❌ Error: Datos inválidos. Por favor, revise los números ingresados.")
except Exception as e:
print(f"❌ Ocurrió un error de cálculo inesperado: {e}")
# Programa Principal
print("📉 Verificador de Estabilidad de Taludes")
c_str = input("Ingrese la cohesión del suelo (kPa): ")
w_str = input("Ingrese el peso de la masa de suelo (kN): ")
phi_str = input("Ingrese el ángulo de fricción interna (°): ")
calcular_fs_talud(c_str, w_str, phi_str)
💡 Prompts Sugeridos para IA:
"¿Qué es el módulo 'math' en Python y qué tipo de funciones contiene?"
,
"¿Por qué las funciones trigonométricas en Python (
sin,
cos,
tan) esperan los ángulos en radianes y no en grados?"
"Escribe el código en Python para convertir un ángulo de grados a radianes."
,
"Quiero un solo bloque 'except' que atrape tanto
ValueErrorcomo
ZeroDivisionError. ¿Cómo lo escribo?"
El siguiente es el detalle para la Semana 8, un momento clave donde los estudiantes consolidan todo lo aprendido en el primer bloque del curso.
Esta semana es diferente. No introduciremos conceptos nuevos. En su lugar, nos dedicaremos por completo a nuestro primer gran hito: construir un programa completo, funcional y robusto desde cero. Es el momento de conectar todas las piezas que hemos aprendido (variables, condicionales, bucles, funciones, diccionarios y manejo de errores) para crear una herramienta de ingeniería útil. El trabajo de esta semana culminará con la entrega de la Tarea 1.
A continuación se presentan las alternativas de proyecto para el Hito 1 (Tarea 1), diseñadas específicamente para los perfiles de Ingeniería Civil, Agrícola y Agroindustrial.
Nota Importante: La estructura de la entrega y los recursos de apoyo son los mismos para las tres Ingenierías. La “Checklist de Entrega”, los “Consejos para el Éxito” y los “Prompts Sugeridos para IA”, que se muestran sólo para Ingeniería Civil. El objetivo es el mismo: integrar todos los conceptos del Bloque 1 en una herramienta funcional.
El objetivo es desarrollar una calculadora en Python que estime la cantidad y el costo de los materiales necesarios para construir un cimiento de concreto simple (zapata aislada). El programa debe ser interactivo y fácil de usar para un ingeniero o maestro de obra.
Requisitos Funcionales:
try-except
) para validar todas
las entradas del usuario, evitando que el programa se detenga por
ingresos inválidos (texto en lugar de números, valores negativos,
etc.).Esta semana, el rol del docente es ser un guía y un consultor. El código no se entrega “hecho”, sino que se ayuda a los estudiantes a construirlo.
.py
(o un enlace a un Google Colab Notebook) con el código completo.calcular_costo_total()
es mucho más claro que
calc()
. Un buen nombramiento hace tu código más fácil de
leer y depurar."Estoy empezando un proyecto para una calculadora de costos en Python. ¿Cómo puedo descomponer este gran problema en funciones más pequeñas y manejables? Dame una estructura de funciones sugerida."
"Mi programa me da un error que no entiendo: [pegar el error]. Este es el bloque de código que lo causa: [pegar el código]. ¿Puedes explicarme qué significa este error y dónde podría estar el problema?"
"Tengo un diccionario con precios, como
precios =
{‘cemento’: 8, ‘arena’:
20}. También tengo otro diccionario con las cantidades necesarias, como
cantidades
= {‘cemento’: 14, ‘arena’:
1.2}. ¿Cómo puedo escribir un bucle en Python para calcular el costo total multiplicando las cantidades por sus precios correspondientes?"
"Este es el código de mi función [pegar función]. Funciona, pero se ve muy largo y repetitivo. ¿Puedes darme sugerencias para hacerlo más corto y limpio?"
El objetivo es desarrollar una calculadora que ayude a un agricultor a determinar las necesidades de fertilizantes y su costo estimado para un cultivo específico en una superficie determinada.
Requisitos Funcionales:
while
para realizar múltiples consultas.python REQUERIMIENTOS = { "maiz": {"N": 120, "P": 60, "K": 60}, "tomate": {"N": 150, "P": 80, "K": 200} }
python COSTOS_FERTILIZANTE = { "urea_usd_saco_50kg": 25.00, # Aporta Nitrógeno (N) "fosfato_usd_saco_50kg": 30.00 # Aporta Fósforo (P) }
try-except
): El programa
debe validar que el área ingresada sea un número positivo y manejar
cualquier otro error de entrada sin detenerse.El objetivo es desarrollar una herramienta que calcule los costos de materia prima para producir un lote de un producto procesado, como mermelada o néctar.
Requisitos Funcionales:
while
,
permitiendo al usuario cotizar diferentes producciones hasta que decida
salir.python RECETAS = { "mermelada_fresa": {"fruta_kg": 1.1, "azucar_kg": 0.6, "pectina_g": 5}, "nectar_mango": {"pulpa_fruta_kg": 0.5, "agua_L": 0.6, "azucar_kg": 0.1} }
python COSTOS_INGREDIENTES = { "fruta_kg": 1.50, "azucar_kg": 0.90, "pectina_g": 0.05, "pulpa_fruta_kg": 1.20, "agua_L": 0.01 }
try-except
): Validar que la
cantidad de producción ingresada sea un número positivo y manejar otros
errores de entrada.Continuemos con el Bloque 2, una fase emocionante donde los estudiantes transformarán sus conocimientos en aplicaciones más robustas y profesionales.
Esta semana marca un punto de inflexión en el curso. Daremos nuestro
primer paso fuera del entorno de aprendizaje de Google Colab para entrar
al mundo del desarrollo de software profesional. Aprenderemos a
estructurar nuestros proyectos en archivos .py
, a gestionar
dependencias con entornos virtuales y a ejecutar nuestros programas
desde la terminal, usando una herramienta estándar en la industria como
Visual Studio Code (VSCode).
Imagina el siguiente escenario, aplicable a cualquiera de los proyectos del Hito 1:
Tu calculadora de costos (de cimientos, de fertilizantes o de producción) ha sido un éxito. Es tan útil que tu supervisor o un colega quiere empezar a usarla regularmente. Sin embargo, pedirle que abra un Google Colab Notebook cada vez que necesita un cálculo no es práctico ni profesional. Además, quieren integrar tu herramienta con otros sistemas en el futuro.
El reto: Se te ha encargado la tarea de convertir tu “cuaderno de prototipos” en un “programa” formal. Debe ser un script de Python (
.py
) independiente, limpio y ejecutable desde cualquier computador que tenga Python instalado, sin necesidad de un navegador web. ¿Cómo realizamos esta transición?
El objetivo de esta semana es que cada estudiante tome el código de su Tarea 1 y lo refactorice en un proyecto local estructurado.
Paso a Paso de la Migración:
MiCalculadoraProfesional
).
Abrir esta carpeta con VSCode
(Archivo > Abrir Carpeta...
).venv
):
Abrir una nueva terminal dentro de VSCode
(Terminal > Nuevo terminal
). Ejecutar los comandos para
crear y activar un entorno virtual. Esto aísla las dependencias del
proyecto.
bash # Crear el entorno python -m venv venv # Activar el entorno (en Windows) .\venv\Scripts\activate # Activar el entorno (en macOS/Linux) source venv/bin/activate
main.py
.main.py
. La clave
aquí es organizarlo de manera estructurada (ver el código de ejemplo más
abajo). Las definiciones de funciones van primero, y el código que
“ejecuta” el programa va dentro de una función main()
.bash python main.py
Código de Ejemplo: Estructura de un Script Profesional
(main.py
)
# 1. IMPORTS: Todas las librerías que se usarán van al inicio.
# (Para este proyecto, puede que no necesitemos ninguna por ahora)
import os # Ejemplo de import
# 2. CONSTANTES Y "BASES DE DATOS":
# Las variables que no cambian (constantes) y los diccionarios de datos
# se definen aquí, en mayúsculas por convención.
COSTOS_INGREDIENTES = {
"fruta_kg": 1.50,
"azucar_kg": 0.90,
}
RECETAS = {
"mermelada_fresa": {"fruta_kg": 1.1, "azucar_kg": 0.6},
}
# 3. DEFINICIÓN DE FUNCIONES:
# Cada función debe hacer una sola cosa bien.
def calcular_costo_lote(producto, cantidad):
"""Calcula el costo total de materia prima para un lote de producción."""
# ... (Lógica de la función aquí) ...
# Se asume que esta función usa los diccionarios de arriba
costo_total = 100 # Valor de ejemplo
return costo_total
def mostrar_menu():
"""Imprime las opciones disponibles para el usuario."""
print("\n--- Menú Principal ---")
print("1. Calcular costo de lote")
print("2. Salir")
return input("Seleccione una opción: ")
# 4. FUNCIÓN PRINCIPAL (main):
# Esta función controla el flujo principal de la aplicación.
def main():
"""Punto de entrada y bucle principal del programa."""
print("🚀 Bienvenido al Sistema de Costeo Agroindustrial")
while True:
opcion = mostrar_menu()
if opcion == '1':
# Aquí iría el código para pedir los datos y llamar a la función de cálculo
costo = calcular_costo_lote("mermelada_fresa", 50)
print(f"El costo estimado es: ${costo:.2f}")
elif opcion == '2':
print("Saliendo del programa. ¡Hasta luego!")
break
else:
print("❌ Opción no válida. Intente de nuevo.")
# 5. PUNTO DE ENTRADA:
# Esta construcción asegura que la función main() solo se ejecute
# cuando el archivo es corrido directamente. Es una convención estándar.
if __name__ == "__main__":
main()
💡 Prompts Sugeridos para IA:
"Estoy acostumbrado a Google Colab. ¿Cuáles son las ventajas de usar un entorno de desarrollo local como VSCode para proyectos más serios?"
,
"¿Qué es la 'terminal' o 'línea de comandos' y por qué un programador profesional la utiliza tanto?"
"En un script de Python, ¿cuál es el propósito de la construcción
if
name ==
“main”:? ¿Por qué no simplemente llamo a mi función
main()al final del archivo?"
"He copiado mi código de Colab a un archivo .py en VSCode, pero cuando lo ejecuto en la terminal no pasa nada, no me pide ningún dato. ¿Qué podría estar faltando en mi script?"
(Respuesta probable: olvidaron llamar a la función principal dentro del
bloque if __name__ == "__main__":
)."¿Qué es una 'extensión' en VSCode? ¿Puedes recomendarme 3 extensiones esenciales para programar en Python?"
(Respuesta sugerida: Python de Microsoft, Pylance, Black
Formatter).Continuamos con el plan de estudio para las Semanas 10 y 11, donde introducimos un paradigma que cambiará la forma en que los estudiantes estructuran su código: la Programación Orientada a Objetos (POO).
Durante estas dos semanas, daremos un paso fundamental para escribir código más organizado, reutilizable y fácil de entender. Aprenderemos a modelar el mundo real dentro de nuestros programas. En lugar de tener datos por un lado y funciones por otro, la POO nos permite crear “bloques de construcción” llamados Objetos. Cada objeto tiene sus propias características (atributos) y sus propios comportamientos (métodos).
La analogía es simple: una class
es como el plano de un
coche, define todas sus partes y lo que puede hacer. Un
object
es el coche real que construimos a partir de ese
plano; podemos construir muchos coches, y cada uno tendrá su propio
color, kilometraje, etc., pero todos compartirán la misma estructura del
plano.
Situación de Interés en Ingeniería Agrícola 🌾:
Necesitamos gestionar múltiples parcelas en una finca. Cada parcela
tiene su propia área, su propio cultivo y su propio nivel de humedad.
Queremos un sistema que nos permita tratar a cada Parcela
como una unidad individual, a la que podamos dar órdenes como “regar” o
“mostrar estado”.
Situación de Interés en Ingeniería Agroindustrial
🥫: En una planta, cada lote de producción es único: tiene un
código, una fecha de elaboración y una cantidad. Se necesita una forma
de representar cada LoteDeProduccion
como una entidad
digital. Esta entidad debe ser capaz de, por sí misma, calcular su
propia fecha de vencimiento o generar la información para su
etiqueta.
Situación de Interés en Ingeniería Civil 🌉: Un
ingeniero está diseñando varios elementos estructurales. En lugar de
calcular el volumen y el peso de cada viga rectangular con funciones
sueltas, quiere crear un “molde” o plantilla para cualquier
VigaRectangular
. A partir de esta plantilla, podrá crear
vigas virtuales, cada una con sus propias dimensiones, y pedirle a cada
una que calcule su propio volumen y peso.
A continuación, modelamos cada escenario utilizando clases y objetos en Python.
class Parcela
)Paso a Paso del Código:
modelos_agricolas.py
.class Parcela:
.__init__
: este
método recibirá los atributos iniciales de cada parcela (nombre, área,
cultivo, humedad) y los guardará usando self
.regar(self, litros_m2)
: este método modificará el
atributo self.humedad
.mostrar_estado(self)
: este método imprimirá un
resumen bien formateado de todos los atributos de la parcela.main.py
, importar la
clase (from modelos_agricolas import Parcela
).Parcela
, cada uno con datos diferentes.Código de Ejemplo:
Archivo: modelos_agricolas.py
class Parcela:
"""Representa una parcela de cultivo con sus atributos y acciones."""
def __init__(self, nombre, area_ha, cultivo_actual, humedad_inicial):
self.nombre = nombre
self.area_ha = area_ha
self.cultivo_actual = cultivo_actual
self.humedad_porcentaje = humedad_inicial
print(f"✅ Parcela '{self.nombre}' creada.")
def regar(self, cantidad_litros_por_m2):
"""Simula el riego, aumentando el nivel de humedad."""
print(f"💧 Regando la parcela '{self.nombre}'...")
self.humedad_porcentaje += cantidad_litros_por_m2 * 0.1 # Simulación simple
if self.humedad_porcentaje > 100:
self.humedad_porcentaje = 100
def mostrar_estado(self):
"""Muestra un resumen de la parcela."""
print(f"\n--- Estado de la Parcela: {self.nombre} ---")
print(f" Área: {self.area_ha} ha")
print(f" Cultivo: {self.cultivo_actual}")
print(f" Humedad Actual: {self.humedad_porcentaje:.1f}%")
print("--------------------------------------")
Archivo: main.py
from modelos_agricolas import Parcela
# Creamos los objetos
parcela_norte = Parcela(nombre="Lote Norte", area_ha=5, cultivo_actual="Maíz", humedad_inicial=45.0)
parcela_sur = Parcela(nombre="Lote Sur", area_ha=10, cultivo_actual="Sorgo", humedad_inicial=35.0)
# Mostramos su estado inicial
parcela_norte.mostrar_estado()
parcela_sur.mostrar_estado()
# Interactuamos con un objeto específico
parcela_sur.regar(cantidad_litros_por_m2=200)
# Mostramos el estado final
print("\n*** DESPUÉS DEL RIEGO ***")
parcela_norte.mostrar_estado()
parcela_sur.mostrar_estado()
💡 Prompts Sugeridos para IA:
"Explícame el concepto de 'clase' y 'objeto' en POO con una analogía del mundo real, como un molde para galletas y las galletas que horneas."
,
"En una clase de Python, ¿qué es 'self' y por qué se usa en los métodos y en el constructor
init?"
"Escribe una clase simple en Python para representar un 'Tractor'. Debe tener atributos como 'modelo' y 'horas_de_uso', y un método llamado 'registrar_trabajo(horas)' que incremente las horas de uso."
class LoteDeProduccion
)Paso a Paso del Código:
modelos_industriales.py
. Importar el
módulo datetime
y timedelta
para manejar
fechas.class LoteDeProduccion:
.__init__
, guardar los atributos:
id_lote
, producto
, cantidad
,
fecha_elaboracion
.calcular_vencimiento(self, dias_vida_util)
que tome la
fecha_elaboracion
, le sume los días de vida útil y devuelva
la fecha de vencimiento.generar_etiqueta(self)
que devuelva
un string con toda la información del lote, listo para ser impreso.main.py
, importar la clase, crear objetos de lotes
diferentes y usar sus métodos para obtener las etiquetas y fechas de
vencimiento.Código de Ejemplo:
Archivo: modelos_industriales.py
from datetime import date, timedelta
class LoteDeProduccion:
"""Modela un lote de producción con su información y métodos asociados."""
def __init__(self, id_lote, producto, cantidad_kg):
self.id_lote = id_lote
self.producto = producto
self.cantidad_kg = cantidad_kg
self.fecha_elaboracion = date.today() # Asigna la fecha actual
def calcular_vencimiento(self, dias_vida_util):
"""Calcula la fecha de vencimiento a partir de la elaboración."""
return self.fecha_elaboracion + timedelta(days=dias_vida_util)
def generar_etiqueta(self):
"""Genera un string formateado para la etiqueta del lote."""
return f"--- ETIQUETA DE LOTE ---\nID: {self.id_lote}\nProducto: {self.producto}\nCantidad: {self.cantidad_kg} kg\nElaborado: {self.fecha_elaboracion.strftime('%Y-%m-%d')}"
Archivo: main.py
from modelos_industriales import LoteDeProduccion
# Creamos instancias para diferentes productos
lote_mermelada = LoteDeProduccion(id_lote="MERM-001", producto="Mermelada de Fresa", cantidad_kg=500)
lote_nectar = LoteDeProduccion(id_lote="NECT-045", producto="Néctar de Mango", cantidad_kg=1200)
# Usamos los métodos
vencimiento_mermelada = lote_mermelada.calcular_vencimiento(dias_vida_util=365)
etiqueta_nectar = lote_nectar.generar_etiqueta()
print(lote_mermelada.generar_etiqueta())
print(f"Fecha de Vencimiento: {vencimiento_mermelada.strftime('%Y-%m-%d')}\n")
print(etiqueta_nectar)
vencimiento_nectar = lote_nectar.calcular_vencimiento(dias_vida_util=180)
print(f"Fecha de Vencimiento: {vencimiento_nectar.strftime('%Y-%m-%d')}")
💡 Prompts Sugeridos para IA:
"¿Qué es un método constructor en POO y cuál es su nombre estándar en Python?"
,
"¿Puedo crear un objeto a partir de una clase sin pasarle todos los parámetros que pide el
init? ¿Qué pasaría?"
"Necesito trabajar con fechas en Python. ¿Qué librería debo importar y cómo puedo obtener la fecha de hoy?"
,
"Tengo una fecha, ¿cómo le sumo 30 días para obtener una nueva fecha?"
class VigaRectangular
)Paso a Paso del Código:
modelos_civiles.py
.class VigaRectangular:
.__init__
, recibir y guardar largo
,
ancho
y alto
.calcular_volumen(self)
que
multiplique las tres dimensiones.calcular_peso(self, densidad_kg_m3)
que primero llame a self.calcular_volumen()
y luego
multiplique el resultado por la densidad recibida. Esto muestra cómo los
métodos de un mismo objeto pueden colaborar entre sí.main.py
, importar la clase. Crear un diccionario de
densidades. Crear objetos de vigas y usar sus métodos, pasándoles la
densidad correspondiente del diccionario.Código de Ejemplo:
Archivo: modelos_civiles.py
class VigaRectangular:
"""Representa una viga rectangular y permite calcular sus propiedades."""
def __init__(self, id_viga, largo, ancho, alto):
self.id_viga = id_viga
self.largo_m = largo
self.ancho_m = ancho
self.alto_m = alto
def calcular_volumen(self):
"""Calcula y devuelve el volumen de la viga en metros cúbicos."""
return self.largo_m * self.ancho_m * self.alto_m
def calcular_peso(self, densidad_kg_m3):
"""Calcula el peso de la viga usando su volumen y una densidad dada."""
volumen = self.calcular_volumen() # Un método llamando a otro
peso = volumen * densidad_kg_m3
return peso
Archivo: main.py
from modelos_civiles import VigaRectangular
DENSIDADES = {"concreto": 2400, "acero": 7850}
# Creamos las vigas virtuales
viga_01 = VigaRectangular(id_viga="V-01", largo=6.0, ancho=0.3, alto=0.5)
viga_02 = VigaRectangular(id_viga="V-02", largo=8.0, ancho=0.4, alto=0.6)
# Calculamos sus propiedades
volumen_viga_01 = viga_01.calcular_volumen()
peso_viga_01 = viga_01.calcular_peso(densidad_kg_m3=DENSIDADES["concreto"])
print(f"--- Viga {viga_01.id_viga} ---")
print(f" Volumen: {volumen_viga_01:.2f} m³")
print(f" Peso (Concreto): {peso_viga_01:.2f} kg")
peso_viga_02 = viga_02.calcular_peso(densidad_kg_m3=DENSIDADES["concreto"])
print(f"\n--- Viga {viga_02.id_viga} ---")
print(f" Peso (Concreto): {peso_viga_02:.2f} kg")
💡 Prompts Sugeridos para IA:
"En POO, ¿cuál es la diferencia entre un atributo de clase y un atributo de instancia? Dame un ejemplo."
"Dentro de un método de una clase, ¿cómo puedo llamar a otro método de la misma clase?"
,
"Quiero que un método de mi clase devuelva dos valores a la vez, por ejemplo, el área y el perímetro. ¿Cómo lo hago?"
Avancemos hacia una de las partes más gratificantes del curso, donde se verá cómo los programas lógicos se transforman en aplicaciones visuales e interactivas.
Durante estas dos semanas, conectaremos todo lo que hemos hecho.
Aprenderemos a usar Módulos y Paquetes (como
streamlit
y nuestras propias clases guardadas en otros
archivos) para construir aplicaciones completas. El objetivo principal
es tomar las clases que diseñamos en las semanas de POO y crear una
interfaz gráfica de usuario (GUI) en formato de página
web. Esto permitirá que cualquier persona, sin necesidad de ver o
entender el código, pueda utilizar las herramientas que hemos
creado.
Tus clases
Parcela
,LoteDeProduccion
oVigaRectangular
son potentes y funcionan a la perfección. Sin embargo, para usarlas, un colega tendría que abrir el código, crear los objetos manualmente y llamar a los métodos. Esto es ineficiente y propenso a errores.El reto: Se te ha asignado la tarea de construir una “fachada” o “panel de control” amigable para tus clases. Debes crear una aplicación web simple donde un usuario pueda ingresar los datos en casillas y botones, y ver los resultados de forma clara y visual, sin tocar una sola línea de código. ¿Cómo usamos Streamlit para “envolver” nuestros objetos en una interfaz gráfica?
El objetivo es crear un nuevo script app.py
que importe
las clases previamente definidas y las utilice como el “motor” de la
aplicación Streamlit.
Paso a Paso del Código:
app.py
, en la misma carpeta
donde tienes modelos_agricolas.py
.app.py
, importar streamlit
y la clase
Parcela
:
from modelos_agricolas import Parcela
.st.title
) y una
descripción.Parcela
: st.text_input
para el
nombre, st.number_input
para el área y la humedad, y
st.selectbox
para el tipo de cultivo.st.button("Crear y Analizar Parcela")
.if
que se activa con el botón, tomar los
valores de los widgets, crear una instancia de la clase
Parcela
..mostrar_estado()
del objeto creado y
mostrar la información en la página.Código de Ejemplo (app.py
):
import streamlit as st
from modelos_agricolas import Parcela # Importamos nuestra clase
# --- Configuración de la Interfaz ---
st.set_page_config(page_title="Gestor de Parcelas", page_icon="🌾")
st.title("🌾 Panel de Control de Parcelas Agrícolas")
st.write("Crea y gestiona las parcelas de tu finca de forma virtual.")
# --- Formulario de Entrada de Datos ---
st.header("Registrar Nueva Parcela")
with st.form("nueva_parcela_form"):
nombre_parcela = st.text_input("Nombre o ID de la Parcela (ej. Lote-01):")
area_parcela = st.number_input("Área (en hectáreas):", min_value=0.1, step=0.1)
cultivo = st.selectbox("Cultivo Actual:", ["Maíz", "Sorgo", "Tomate", "Ninguno"])
humedad = st.slider("Humedad Inicial (%):", 0, 100, 50)
# Botón de envío del formulario
submitted = st.form_submit_button("Crear Parcela")
# --- Lógica de la Aplicación ---
if submitted:
if not nombre_parcela:
st.warning("Por favor, ingresa un nombre para la parcela.")
else:
# 6. Creamos el objeto con los datos del formulario
parcela_obj = Parcela(
nombre=nombre_parcela,
area_ha=area_parcela,
cultivo_actual=cultivo,
humedad_inicial=float(humedad)
)
st.success(f"¡Parcela '{parcela_obj.nombre}' creada con éxito!")
# 7. Usamos el método del objeto para mostrar su estado
# Para mostrarlo en Streamlit, modificamos el método para que devuelva un string
# O creamos una función que lo formatee aquí.
st.subheader("Estado Actual de la Parcela")
# Usando st.metric para una visualización más atractiva
col1, col2, col3 = st.columns(3)
col1.metric("Área", f"{parcela_obj.area_ha} ha")
col2.metric("Cultivo", parcela_obj.cultivo_actual)
col3.metric("Humedad", f"{parcela_obj.humedad_porcentaje:.1f}%")
💡 Prompts Sugeridos para IA:
"¿Cuál es la diferencia entre un módulo y un paquete en Python?"
,
"Tengo dos archivos .py en la misma carpeta. ¿Cómo importo una clase de un archivo para usarla en el otro?"
"¿Qué es
st.formen Streamlit y cuándo debería usarlo en lugar de poner los widgets directamente en la página?"
,
"¿Cómo puedo mostrar datos en columnas una al lado de la otra en Streamlit?"
Paso a Paso del Código:
app.py
. Importar streamlit
y la
clase LoteDeProduccion
.st.title
, etc.st.text_input
para el ID, st.selectbox
para el
nombre del producto, st.number_input
para la cantidad.st.slider
para que el usuario defina
los “días de vida útil” del producto.LoteDeProduccion
..generar_etiqueta()
y
.calcular_vencimiento()
.st.text_area
y la
fecha de vencimiento con st.success
.Código de Ejemplo (app.py
):
import streamlit as st
from modelos_industriales import LoteDeProduccion # Importamos la clase
st.title("🥫 Gestor de Lotes de Producción")
with st.expander("➕ Registrar Nuevo Lote de Producción", expanded=True):
id_lote = st.text_input("ID del Lote (ej. MERM-002):")
producto = st.selectbox("Producto:", ["Mermelada de Fresa", "Néctar de Mango", "Salsa de Tomate"])
cantidad = st.number_input("Cantidad Producida (kg):", min_value=1.0)
vida_util = st.slider("Días de Vida Útil del Producto:", 30, 730, 365)
if st.button("Registrar y Generar Etiqueta"):
if not id_lote or not producto:
st.error("El ID del lote y el producto son obligatorios.")
else:
# 5. Creamos el objeto
lote_obj = LoteDeProduccion(id_lote, producto, cantidad)
st.balloons()
st.subheader("Etiqueta y Datos del Lote Generados")
# 6. Llamamos a los métodos
etiqueta = lote_obj.generar_etiqueta()
fecha_vencimiento = lote_obj.calcular_vencimiento(vida_util)
# 7. Mostramos los resultados
st.text_area("Etiqueta Generada", value=etiqueta, height=150)
st.success(f"Fecha de Vencimiento Calculada: {fecha_vencimiento.strftime('%d de %B de %Y')}")
💡 Prompts Sugeridos para IA:
"¿Cómo puedo hacer que un formulario o una sección de mi app de Streamlit aparezca colapsada por defecto y se expanda al hacer clic?"
,
"Quiero mostrar una fecha en un formato amigable como '07 de Agosto de 2025'. ¿Cómo formateo un objeto de fecha en Python de esa manera?"
"Tengo una clase en un archivo y la estoy usando en mi app de Streamlit. Si hago un cambio en la clase, ¿tengo que reiniciar mi app de Streamlit para que vea los cambios? ¿Cómo funciona eso?"
Paso a Paso del Código:
app.py
. Importar streamlit
, la clase
VigaRectangular
y el diccionario
DENSIDADES
.st.number_input
para las dimensiones (largo,
ancho, alto).st.selectbox
para que el usuario elija un
material. Las opciones del selectbox deben ser las llaves del
diccionario DENSIDADES
.VigaRectangular
..calcular_volumen()
y
.calcular_peso()
, pasándole la densidad.st.metric
para una
visualización de impacto.Código de Ejemplo (app.py
):
import streamlit as st
from modelos_civiles import VigaRectangular, DENSIDADES # Importamos clase y diccionario
st.title("🌉 Calculadora de Propiedades de Vigas")
st.sidebar.header("Parámetros de la Viga")
id_viga = st.sidebar.text_input("ID de la Viga:", "V-101")
largo = st.sidebar.number_input("Largo (m):", value=6.0)
ancho = st.sidebar.number_input("Ancho (m):", value=0.3)
alto = st.sidebar.number_input("Alto (m):", value=0.5)
material = st.sidebar.selectbox("Material:", options=list(DENSIDADES.keys()))
if st.sidebar.button("Calcular Propiedades"):
# 5. Creamos la instancia
viga_obj = VigaRectangular(id_viga, largo, ancho, alto)
# 6. Obtenemos la densidad
densidad_seleccionada = DENSIDADES[material]
# 7. Llamamos a los métodos
volumen = viga_obj.calcular_volumen()
peso = viga_obj.calcular_peso(densidad_seleccionada)
st.header(f"Resultados para la Viga: {viga_obj.id_viga}")
# 8. Mostramos resultados con st.metric
col1, col2 = st.columns(2)
col1.metric("Volumen", f"{volumen:.2f} m³")
col2.metric(f"Peso ({material.capitalize()})", f"{peso:,.0f} kg")
else:
st.info("Ingrese los parámetros en la barra lateral y presione 'Calcular'.")
💡 Prompts Sugeridos para IA:
"¿Cómo puedo crear una barra lateral en mi aplicación de Streamlit para poner allí todos los controles de entrada?"
,
"Tengo un diccionario en Python. ¿Cómo puedo obtener una lista de todas sus llaves para usarla como opciones en un
st.selectbox?"
"En Python, tengo un número muy grande como 125430.7. ¿Cómo puedo formatearlo para que se muestre con comas como separadores de miles y sin decimales, como '125,431'?"
Avancemos a la Semana 14. Esta es una semana conceptualmente muy importante, ya que aborda un pilar fundamental en el desarrollo de aplicaciones interactivas: el manejo del estado.
Hasta ahora, nuestras aplicaciones tienen un pequeño problema: no tienen memoria. Cada vez que interactuamos con un widget (un botón, un slider), Streamlit vuelve a ejecutar nuestro script de Python desde el principio. Esto significa que cualquier variable que hayamos creado se reinicia.
El objetivo de esta semana es aprender a solucionar esto.
Introduciremos el Manejo de Estado a través de
st.session_state
, un objeto especial de Streamlit que
funciona como un “diccionario con memoria” y que sobrevive a los
reinicios del script. Esto nos permitirá crear aplicaciones mucho más
complejas y útiles.
Tu aplicación es genial para analizar un solo objeto a la vez (una parcela, un lote, una viga). Pero en el mundo real, los proyectos son más complejos.
- Ingeniería Agrícola: Un agrónomo no planifica un solo cultivo, sino una secuencia de rotación para los próximos años en la misma parcela.
- Ingeniería Agroindustrial: Un jefe de planta no gestiona un solo lote, sino una lista de todos los lotes producidos en un día para su trazabilidad.
- Ingeniería Civil: Un ingeniero de costos no calcula una sola viga, sino que elabora un listado completo de materiales para toda una estructura.
El reto: ¿Cómo permitimos que el usuario agregue elementos a una lista uno por uno, sin que la lista se borre cada vez que hace clic en el botón “Añadir”? Aquí es donde
st.session_state
se vuelve indispensable.
A continuación, implementamos la solución para cada escenario,
demostrando el uso de st.session_state
.
Paso a Paso del Código:
streamlit
.st.session_state
. Si no existe, crearla como una lista
vacía. Esto es crucial y se hace solo una vez, la primera vez que se
ejecuta la app.st.selectbox
para elegir un
cultivo y un st.button
para añadirlo..append()
para añadir el
cultivo seleccionado a la lista que está guardada en
st.session_state.rotacion
.st.session_state.rotacion
.Código de Ejemplo (app.py
):
import streamlit as st
st.title("🌱 Planificador de Rotación de Cultivos")
# 2. Inicialización del estado de sesión
if 'plan_rotacion' not in st.session_state:
st.session_state.plan_rotacion = []
# --- Controles para añadir cultivos ---
cultivos_disponibles = ["Maíz", "Soja", "Trigo", "Girasol", "Barbecho (Descanso)"]
cultivo_seleccionado = st.selectbox("Seleccione el cultivo para el siguiente ciclo:", cultivos_disponibles)
if st.button("Añadir al Plan de Rotación"):
# 4. Modificar el estado
st.session_state.plan_rotacion.append(cultivo_seleccionado)
st.success(f"Se añadió '{cultivo_seleccionado}' al plan.")
# --- Mostrar el estado actual ---
st.header("Plan de Rotación Actual")
if not st.session_state.plan_rotacion:
st.info("Aún no se han añadido cultivos al plan.")
else:
for i, cultivo in enumerate(st.session_state.plan_rotacion):
st.write(f"**Año {i+1}:** {cultivo}")
# 6. Botón para reiniciar el estado
if st.button("Limpiar Plan"):
st.session_state.plan_rotacion = []
st.experimental_rerun() # Forzar la recarga de la app para ver el cambio
💡 Prompts Sugeridos para IA:
"¿Qué es el 'estado' en una aplicación web? Explícamelo con una analogía de un carrito de compras online."
,
"¿Por qué mi variable en Streamlit se reinicia cada vez que hago clic en un botón? ¿Cómo funciona el ciclo de ejecución de Streamlit?"
session_state
:
"Muéstrame la forma correcta de inicializar una variable en st.session_state para que solo ocurra una vez."
,
"¿Cuál es la diferencia entre
st.session_state.mi_variable =
valory
st.session_state[‘mi_variable’] =
valor?"
Paso a Paso del Código:
st.session_state.lotes
como una lista vacía
si no existe.st.form
para agrupar los campos de entrada:
id_lote
, producto
y
fecha_elaboracion
.st.session_state.lotes
.st.dataframe
.Código de Ejemplo (app.py
):
import streamlit as st
import pandas as pd
from datetime import date
st.title("📦 Registro de Trazabilidad de Lotes")
# 1. Inicializar estado
if 'lotes_registrados' not in st.session_state:
st.session_state.lotes_registrados = []
# 2. Formulario para registrar un nuevo lote
with st.form("form_lote", clear_on_submit=True):
st.write("### Registrar Nuevo Lote")
id_lote = st.text_input("ID del Lote:")
producto = st.text_input("Nombre del Producto:")
fecha = st.date_input("Fecha de Elaboración", value=date.today())
submitted = st.form_submit_button("Registrar Lote")
if submitted:
# 3. Crear el diccionario
nuevo_lote = {
"ID Lote": id_lote,
"Producto": producto,
"Fecha Elaboración": fecha
}
# 4. Añadir al estado
st.session_state.lotes_registrados.append(nuevo_lote)
st.success(f"Lote {id_lote} registrado con éxito.")
# 5. Mostrar todos los lotes registrados
st.header("Historial de Lotes Registrados")
if st.session_state.lotes_registrados:
# Convertimos la lista de diccionarios a un DataFrame de Pandas para una mejor visualización
df_lotes = pd.DataFrame(st.session_state.lotes_registrados)
st.dataframe(df_lotes)
else:
st.info("No hay lotes registrados en esta sesión.")
💡 Prompts Sugeridos para IA:
session_state
:
"¿Cómo puedo guardar una lista de objetos de mi propia clase en st.session_state?"
"Quiero que los campos de mi formulario se borren después de que el usuario presione 'Enviar'. ¿Cómo lo hago en Streamlit?"
"Mi lista en st.session_state parece reiniciarse. ¿Cuál podría ser el error en mi código de inicialización? [pegar código de inicialización]"
.Paso a Paso del Código:
st.session_state.listado_materiales
como
una lista vacía.st.columns
) para una
mejor organización.descripcion
, cantidad
y
unidad
.st.session_state
.st.session_state.listado_materiales
.Código de Ejemplo (app.py
):
import streamlit as st
st.title("🏗️ Listado de Materiales para Cómputos Métricos")
# 1. Inicializar estado
if 'materiales' not in st.session_state:
st.session_state.materiales = []
# 2. Usar columnas para la interfaz
col1, col2 = st.columns([1, 2])
with col1:
st.header("Añadir Ítem")
# 3. Controles
descripcion = st.text_input("Descripción del Material:")
cantidad = st.number_input("Cantidad:", min_value=0.1, step=0.1, format="%.2f")
unidad = st.selectbox("Unidad:", ["m³", "m²", "kg", "sacos", "unidades"])
if st.button("➕ Añadir al Listado"):
if descripcion and cantidad:
# 4. Añadir al estado
nuevo_item = {
"Descripción": descripcion,
"Cantidad": cantidad,
"Unidad": unidad
}
st.session_state.materiales.append(nuevo_item)
else:
st.warning("La descripción y la cantidad son necesarias.")
with col2:
st.header("Listado Actual")
# 5. Mostrar el estado
if not st.session_state.materiales:
st.info("El listado está vacío.")
else:
# Creamos una tabla improvisada
for i, item in enumerate(st.session_state.materiales):
st.markdown(f"**{i+1}. {item['Descripción']}:** {item['Cantidad']} {item['Unidad']}")
# Botón para limpiar todo el listado
if st.sidebar.button("🗑️ Limpiar todo el listado"):
st.session_state.materiales = []
st.experimental_rerun()
💡 Prompts Sugeridos para IA:
session_state
:
"Quiero añadir un botón para eliminar el último elemento que agregué a mi lista en st.session_state. ¿Cómo sería el código para eso?"
"¿Hay alguna forma mejor de mostrar una lista de diccionarios en Streamlit que no sea un
st.dataframeo un bucle
forcon
st.write? ¿Qué es
st.data_editor?"
"Mi aplicación de Streamlit está creciendo y el archivo app.py es muy largo. ¿Cómo puedo organizar mi código en múltiples archivos e importarlos correctamente?"
Abordemos la penúltima semana del curso, un momento crucial donde todo el aprendizaje del semestre converge en el proyecto final.
Esta es la semana cumbre. Todo lo que hemos aprendido, desde la
primera variable hasta el manejo de estado, se une aquí. El objetivo de
esta semana es que cada uno de ustedes se dedique por completo a
desarrollar la Tarea 2, una aplicación web interactiva
y funcional que no solo resuelva un problema de ingeniería, sino que
también demuestre su habilidad para estructurar código de manera
profesional (usando Clases) y crear una experiencia de usuario dinámica
(usando Streamlit y st.session_state
).
A continuación se presentan tres opciones de proyecto, una para cada especialidad. Elige la que más te interese. Todas comparten el mismo nivel de complejidad y deben cumplir con los mismos requisitos técnicos.
Parcelas
de cultivo en una finca
virtual.st.session_state
para mantener una lista de
objetos de tu clase Parcela
.Parcela
y añadirlas a la lista
en el estado de la sesión..mostrar_estado()
..regar()
del objeto específico, actualizando su humedad en
el session_state
. El cambio debe reflejarse inmediatamente
en la interfaz.st.expander
o
st.container
para organizar la información de cada parcela
de forma ordenada.st.session_state
para gestionar una lista de
objetos de tu clase LoteDeProduccion
.st.form
permitirá registrar nuevos lotes, que se añadirán a la lista en el
estado.st.dataframe
).st.text_input
) donde el usuario pueda escribir un
id_lote
. La aplicación deberá encontrar el objeto
correspondiente en la lista del session_state
y mostrar su
etiqueta detallada.self.estado = "Despachado"
) y la tabla principal debe
reflejar este cambio.st.session_state
para mantener una lista de
objetos de tu clase VigaRectangular
(o una clase
ElementoEstructural
más genérica).st.session_state
para calcular y
mostrar los totales consolidados del proyecto:
app.py
, modelos_*.py
,
requirements.txt
).st.session_state
debe ser correcto y permitir la
interactividad requerida.st.session_state
.st.write(st.session_state)
en tu app. Esto te mostrará en
vivo todo lo que está guardado y te ayudará a encontrar errores.if st.button(...)
. Crea una función
(ej. agregar_material_al_estado
) y llámala desde el bloque
del botón. Esto mantiene tu código de la interfaz limpio."Estoy construyendo una app en Streamlit y necesito gestionar una lista de objetos de mi clase 'Producto'. Muéstrame un ejemplo de código completo que inicialice el estado, tenga un formulario para añadir nuevos productos a la lista y muestre la lista actualizada."
"En mi app de Streamlit, cuando hago clic en un botón para modificar un ítem en una lista dentro de st.session_state, parece que se modifica el ítem equivocado o nada cambia. ¿Cuáles son los errores comunes al actualizar listas de objetos en el estado de sesión?"
"Quiero añadir un botón 'Eliminar' al lado de cada ítem en mi lista mostrada en Streamlit. ¿Cómo puedo pasar el índice o el ID del ítem a la función de borrado cuando se hace clic en el botón?"
"Mi archivo app.py se está haciendo muy grande. ¿Cuál es una buena manera de estructurar un proyecto de Streamlit más complejo en múltiples archivos .py?"
Llegamos a la última y más importante etapa del curso, la Semana 16. Aquí es donde los estudiantes no solo finalizan su trabajo técnico, sino que también aprenden a comunicar su valor, una habilidad esencial para cualquier ingeniero.
¡Felicitaciones por llegar a la semana final! Han recorrido un largo camino desde escribir su primera línea de código hasta construir una aplicación web funcional. Esta semana tiene dos objetivos clave: asegurar que su aplicación esté desplegada y accesible para el mundo, y comunicar eficazmente el problema que resolvieron y la solución que crearon. Recuerden: una herramienta brillante es inútil si nadie entiende para qué sirve o cómo usarla.
Antes de la presentación, su aplicación debe estar funcionando en Streamlit Cloud. Este es el último paso técnico.
requirements.txt
está completo:
Abran su terminal (con el entorno activado) y ejecuten
pip freeze > requirements.txt
una última vez para
asegurarse de que todas las librerías (streamlit
,
pandas
, etc.) están listadas. Este es el error de
despliegue más común.C:\...
), sino relativa al
proyecto.Cada estudiante tendrá un tiempo limitado para presentar su proyecto. La clave es ser conciso, claro y centrarse en la demostración.
session_state
. Si es la calculadora
de costos, muestra cómo se actualizan los totales agregados. Explica los
resultados que la aplicación genera.Lote
y
st.session_state
…”), pero no muestres el código a menos que
te lo pregunten."Ayúdame a crear un guion de 1 minuto para la introducción de mi proyecto. El proyecto es una 'Herramienta de Cómputos Métricos para Ingeniería Civil'. Quiero que sea impactante y que deje claro el problema que resuelve."
"¿Cuáles son las 3 preguntas técnicas más probables que me harían sobre mi proyecto de Streamlit que usa POO y manejo de estado? Dame ejemplos de respuestas claras y concisas."
"Voy a hacer una demostración en vivo de mi software. Dame 5 consejos sobre cómo hablar y qué hacer para mantener a la audiencia interesada y para que mi explicación sea muy clara."
"Este es el resumen de mi proyecto [pegar una descripción de 2-3 párrafos]. Ayúdame a condensarlo en una sola frase poderosa para mi conclusión."