Python de Cero a Pro - Cap.5 Operadores y Condiciones Práctica Resuelta
¡QuéPasaLinux! En este capítulo, realizaremos la práctica de los fundamentos de los operadores y las estructuras de control en Python. Es una forma práctica de aplicar los conceptos teóricos aprendidos en el capítulo anterior.
Síguenos con el tutorial
Section titled “Síguenos con el tutorial”Volver a Página Principal
Ver Codigo en GitLab
✅ Hoja de Respuestas: Ejercicios de Capacitación
Section titled “✅ Hoja de Respuestas: Ejercicios de Capacitación”A continuación se presentan las soluciones técnicas a los retos planteados en la Documentación.
1. Límites de Seguridad (Módulo calculos.py)
Section titled “1. Límites de Seguridad (Módulo calculos.py)”Objetivo: Evitar que la calculadora maneje números excesivamente grandes.
- Modificación: Añadir una validación antes de retornar el valor.
def ejecutar_operacion(simbolo, valor_actual, nuevo_valor): try: # ... (lógica anterior de if/elif) ...
resultado = # (aquí se guarda el cálculo)
# Nueva validación de seguridad if isinstance(resultado, (int, float)) and resultado > 1000000: raise ValueError("Límite superado: El resultado es mayor a 1,000,000")
return resultado except Exception as e: raise e2. Contador de Operaciones (Módulo calculadora.py)
Section titled “2. Contador de Operaciones (Módulo calculadora.py)”Objetivo: Mostrar cuántas veces se ha operado en la sesión actual.
- Modificación: Usar
len(historial)dentro demostrar_interfaz.
# Dentro de mostrar_interfaz, modificar la línea de información:elif i == 2: # Usamos len() para contar los elementos de la lista historial txt_control = f"OPERACIONES REALIZADAS: {len(historial)}"3. Formato de Historial (Módulo calculadora.py)
Section titled “3. Formato de Historial (Módulo calculadora.py)”Objetivo: Cambiar la narrativa del historial de operaciones.
- Modificación: Cambiar el diccionario de nombres y el
append.
# En iniciar_calculadora, crear un mapeo de nombres:nombres_ops = {'+': 'SUMA', '-': 'RESTA', '*': 'MULT', '/': 'DIV', '**': 'POT'}
# Al hacer el append:nombre = nombres_ops.get(op, "OP")historial.append(f"[{nombre}] {num}")4. Confirmación de Salida (Módulo calculadora.py)
Section titled “4. Confirmación de Salida (Módulo calculadora.py)”Objetivo: Implementar una validación de usuario antes de cerrar el programa.
- Modificación: Añadir un
inputde confirmación en el bloque deexit.
if entrada == 'exit': confirmar = input("¿Está seguro que desea salir? (s/n): ").lower() if confirmar == 's': print("Finalizando capacitación...") break else: continue # Regresa al inicio del bucle📃 Código Final
Section titled “📃 Código Final”Este código final incluye todas las mejoras de la hoja de respuestas: límites de seguridad, contador de operaciones, historial formateado y confirmación de salida.
calculadora_pro.py
Section titled “calculadora_pro.py”import os
# --- CAPA DE LÓGICA (Equivalente a calculos.py) ---
def ejecutar_operacion(simbolo, valor_actual, nuevo_valor): """Ejecuta la aritmética y valida límites de seguridad.""" try: operaciones = { '+': lambda a, b: a + b, '-': lambda a, b: a - b, '*': lambda a, b: a * b, '/': lambda a, b: a / b, '//': lambda a, b: a // b, '%': lambda a, b: a % b, '**': lambda a, b: a ** b }
if simbolo in ['/', '//'] and nuevo_valor == 0: raise ZeroDivisionError("No es posible dividir entre cero.")
resultado = operaciones[simbolo](valor_actual, nuevo_valor)
# Ejercicio 1: Límite de seguridad if isinstance(resultado, (int, float)) and resultado > 1000000: raise ValueError("Límite superado (> 1,000,000)")
return resultado except KeyError: raise ValueError(f"Operador '{simbolo}' no soportado.") except Exception as e: raise e
def validar_entrada(entrada): """Convierte la entrada a número de forma segura.""" try: return float(entrada) if '.' in entrada else int(entrada) except ValueError: raise ValueError("Entrada no válida. Use números.")
# --- CAPA DE INTERFAZ (Equivalente a main.py) ---
def limpiar_pantalla(): # Uso de os.name para compatibilidad entre Windows (nt) y Unix (posix) os.system('cls' if os.name == 'nt' else 'clear')
def mostrar_interfaz(acumulado, historial, mensaje=""): limpiar_pantalla() col1, col2 = 45, 35 filas_interfaz = 10
print("=" * (col1 + col2 + 3)) print(f"{' HISTORIAL (LOG)':^{col1}} | {' DASHBOARD DE CONTROL':^{col2}}") print("-" * (col1 + col2 + 3))
# Obtenemos las últimas líneas del historial items_visibles = historial[-(filas_interfaz-1):] if historial else ["Esperando datos..."]
for i in range(filas_interfaz): txt_h = items_visibles[i] if i < len(items_visibles) else "" txt_c = ""
# Mapeo de información en el panel derecho (Ejercicio 2) if i == 0: txt_c = f"OP. REALIZADAS: {len(historial)}" elif i == 1: txt_c = "COMANDOS: clear, exit" elif i == 2: txt_c = "MODOS: +, -, *, /, //, %, **" elif i == filas_interfaz - 1: txt_c = f"TOTAL: {acumulado}"
print(f" {txt_h:<{col1-1}} | {txt_c}")
print("-" * (col1 + col2 + 3)) if mensaje: print(f" [AVISO]: {mensaje}") else: print("")
def iniciar_calculadora(): acumulado, historial, error = 0, [], "" # Mapeo para nombres de historial (Ejercicio 3) nombres_ops = {'+': 'SUMA', '-': 'RESTA', '*': 'MULT', '/': 'DIV', '**': 'POT', '%': 'MOD', '//': 'DIV_E'}
while True: mostrar_interfaz(acumulado, historial, error) error = "" entrada = input(" DIGITE OPERACIÓN >> ").strip().lower()
# Ejercicio 4: Confirmación de salida if entrada == 'exit': if input(" ¿Cerrar aplicación? (s/n): ").lower() == 's': break continue
if entrada == 'clear': acumulado, historial = 0, [] continue
try: op = "" if entrada.startswith(('**', '//')): op, num_str = entrada[:2], entrada[2:] elif entrada[:1] in "+-*/%": op, num_str = entrada[0], entrada[1:] else: # Caso: primer número de la sesión num = validar_entrada(entrada) if not historial: acumulado = num historial.append(f"[INICIO] {num}") else: error = "Falta operador (ej: +5)" continue
num = validar_entrada(num_str) nuevo_total = ejecutar_operacion(op, acumulado, num)
# Formateo de historial (Ejercicio 3) nombre_op = nombres_ops.get(op, "OP") historial.append(f"[{nombre_op}] {num} -> {nuevo_total}")
acumulado = nuevo_total except Exception as e: error = str(e)
if __name__ == "__main__": iniciar_calculadora()Resumen de lo aprendido con este código:
Section titled “Resumen de lo aprendido con este código:”- Refactorización: Cómo una función simple evoluciona para manejar casos de negocio (límites de 1M).
- UX (Experiencia de Usuario): Por qué es importante pedir confirmación antes de cerrar un programa.
- Análisis de Datos: Cómo transformar un símbolo técnico (
+) en algo legible para un reporte ([SUMA]). - Optimización: El uso de diccionarios (
nombres_ops) para evitar múltiples bloquesif/else.
🎓 Arquitectura y Conceptos Avanzados en Python
Section titled “🎓 Arquitectura y Conceptos Avanzados en Python”1. El Módulo os: Interacción con el Sistema
Section titled “1. El Módulo os: Interacción con el Sistema”os.name: Propiedad que detecta el sistema operativo ('nt'para Windows,'posix'para Linux/macOS). Permite que el código sea multiplataforma.os.system(): Ejecuta comandos de la terminal desde el script. Lo usamos para limpiar la pantalla (clsoclear) y crear una interfaz estática.
2. Validación con isinstance()
Section titled “2. Validación con isinstance()”- Control de Tipos: Se utiliza para verificar si una variable pertenece a un tipo específico (ej:
isinstance(resultado, (int, float))). - Seguridad: En nuestra calculadora, asegura que solo apliquemos reglas de negocio (como el límite de 1,000,000) a valores numéricos, evitando errores al comparar cadenas o valores nulos.
3. Manejo de Errores y Excepciones
Section titled “3. Manejo de Errores y Excepciones”ZeroDivisionError: Excepción estándar de Python que capturamos para evitar que el programa se detenga si el usuario intenta dividir por cero.raise: Palabra clave para “lanzar” una excepción manualmente. Es útil cuando el código es técnicamente correcto pero rompe una regla lógica (como el límite de seguridad).try...except: Estructura que “atrapa” los errores. Permite que la calculadora siga funcionando y muestre un aviso amigable en lugar de cerrarse con un error crítico.
4. Manipulación de Datos Dinámicos
Section titled “4. Manipulación de Datos Dinámicos”startswith(): Método de strings para detectar prefijos. Clave para distinguir operadores de 1 carácter (+) de los de 2 caracteres (**,//).append(): Método de listas para acumular el historial. Permite que la interfaz “recuerde” y muestre el progreso del usuario.- Diccionarios para Mapeo: Usamos
nombres_ops = {'+': 'SUMA'}para transformar símbolos técnicos en nombres legibles, haciendo el código más limpio que usar múltiplesif/elif.
5. Diseño de Interfaz (Layout)
Section titled “5. Diseño de Interfaz (Layout)”- F-Strings y Alineación: El uso de modificadores de formato (ej:
{:<45}) garantiza que las columnas y el separador|se mantengan rectos, creando un “Dashboard” profesional en la terminal.