Mini-reto: calculadora por consola con opciones y manejo de errores

Capítulo 7

Tiempo estimado de lectura: 5 minutos

+ Ejercicio

Objetivo del mini-reto

Vas a construir una calculadora por consola con un menú de opciones (sumar, restar, multiplicar, dividir) y manejo de errores para entradas inválidas. El foco del reto no es “hacer cuentas”, sino crear una experiencia robusta: que el programa no se rompa si el usuario escribe texto, deja vacío, elige una opción inexistente o intenta dividir entre cero.

Qué significa “manejo de errores” aquí

En una app de consola, los errores más comunes vienen de dos fuentes: (1) el usuario escribe algo que no se puede convertir al tipo que necesitas (por ejemplo, letras cuando esperas un número), y (2) ocurre un caso inválido durante la operación (por ejemplo, división entre cero). En Python, esto se gestiona con excepciones usando try/except. La idea es: intentas ejecutar una acción “riesgosa” y, si falla, capturas el error y muestras un mensaje claro, sin cerrar el programa.

Errores típicos que vamos a cubrir

  • ValueError: cuando float("abc") falla porque no es un número.
  • ZeroDivisionError: cuando intentas dividir por 0.
  • Opción inválida: cuando el usuario elige algo fuera del menú (esto no es excepción automática; lo validas tú).

Diseño del programa (antes de escribir código)

Para que el reto sea fácil de mantener, usa esta estructura mental:

  • Entrada: leer opción del menú y dos números.
  • Validación: asegurar que la opción existe y que los números son válidos.
  • Proceso: ejecutar la operación elegida.
  • Salida: mostrar el resultado o un mensaje de error.
  • Bucle principal: repetir hasta que el usuario elija salir.

Guía práctica paso a paso

Paso 1: Define el menú y las opciones

El menú debe ser claro y repetirse en cada ciclo. Incluye una opción para salir.

def mostrar_menu():
    print("\n=== Calculadora ===")
    print("1) Sumar")
    print("2) Restar")
    print("3) Multiplicar")
    print("4) Dividir")
    print("0) Salir")

Paso 2: Crea una función para leer números con seguridad

En vez de repetir try/except cada vez que pidas un número, encapsúlalo en una función. Esta función seguirá preguntando hasta recibir un número válido.

Continúa en nuestra aplicación.
  • Escuche el audio con la pantalla apagada.
  • Obtenga un certificado al finalizar.
  • ¡Más de 5000 cursos para que explores!
O continúa leyendo más abajo...
Download App

Descargar la aplicación

def leer_numero(mensaje):
    while True:
        texto = input(mensaje)
        try:
            return float(texto)
        except ValueError:
            print("Entrada inválida. Escribe un número (ej: 3, 2.5, -10).")

Paso 3: Implementa las operaciones con control de casos inválidos

Puedes resolverlo con una función que reciba la opción y los números. Para la división, protege el caso de divisor cero. Aquí tienes una versión que lanza errores controlados con mensajes claros.

def calcular(opcion, a, b):
    if opcion == "1":
        return a + b
    elif opcion == "2":
        return a - b
    elif opcion == "3":
        return a * b
    elif opcion == "4":
        if b == 0:
            raise ZeroDivisionError("No se puede dividir entre cero")
        return a / b
    else:
        raise ValueError("Opción no válida")

Nota: aquí usamos raise para unificar el manejo de errores en un solo lugar (el bucle principal). También podrías devolver None y manejarlo, pero las excepciones te obligan a tratar el problema explícitamente.

Paso 4: Construye el bucle principal con manejo de errores

Este es el “centro de control”: muestra menú, lee opción, decide si salir, pide números y ejecuta. El objetivo es que cualquier fallo se traduzca en un mensaje y el programa continúe.

def main():
    while True:
        mostrar_menu()
        opcion = input("Elige una opción: ").strip()

        if opcion == "0":
            break

        if opcion not in {"1", "2", "3", "4"}:
            print("Opción inválida. Elige 1, 2, 3, 4 o 0.")
            continue

        a = leer_numero("Primer número: ")
        b = leer_numero("Segundo número: ")

        try:
            resultado = calcular(opcion, a, b)
            print(f"Resultado: {resultado}")
        except ZeroDivisionError:
            print("Error: no se puede dividir entre cero.")
        except ValueError as e:
            print(f"Error: {e}")


if __name__ == "__main__":
    main()

Pruebas rápidas (casos que debes intentar)

Antes de dar el reto por terminado, prueba manualmente estos escenarios para confirmar que tu manejo de errores funciona:

  • Elegir una opción inválida: 9, x, vacío.
  • Escribir texto cuando pide números: hola, 3,5 (coma), espacios.
  • Dividir entre cero: opción 4, segundo número 0.
  • Números negativos y decimales: -2, 0.25.

Mejoras opcionales (sub-retos)

1) Formato del resultado

Muestra el resultado con 2 decimales solo si es decimal, o siempre con 2 decimales.

print(f"Resultado: {resultado:.2f}")

2) Confirmación antes de salir

Pide confirmación para evitar salidas accidentales.

if opcion == "0":
    confirmar = input("¿Seguro que quieres salir? (s/n): ").strip().lower()
    if confirmar == "s":
        break
    continue

3) Historial de operaciones (sin listas)

Guarda solo la última operación en una variable de texto y muéstrala en el menú como “último cálculo”.

ultima = "(sin cálculos aún)"
# ...
print(f"Último: {ultima}")
# ...
ultima = f"{a} / {b} = {resultado}"

4) Permitir repetir con los mismos números

Después de un cálculo, pregunta si quieres usar los mismos números para otra operación. Esto te obliga a pensar el flujo del programa y a evitar pedir datos innecesarios.

Checklist del mini-reto

  • El menú se muestra en cada iteración y existe una opción para salir.
  • Si el usuario escribe una opción inválida, el programa no se rompe y vuelve a pedir.
  • Si el usuario escribe un número inválido, se vuelve a pedir hasta que sea válido.
  • La división entre cero se detecta y se informa con un mensaje claro.
  • El programa continúa funcionando después de cualquier error.

Ahora responde el ejercicio sobre el contenido:

En una calculadora por consola con menú, ¿qué enfoque mejora la robustez para manejar entradas inválidas y permitir que el programa continúe?

¡Tienes razón! Felicitaciones, ahora pasa a la página siguiente.

¡Tú error! Inténtalo de nuevo.

Separar la entrada segura (con reintentos) y capturar excepciones como ValueError y ZeroDivisionError en un punto central evita que el programa se rompa y permite mostrar mensajes claros y seguir ejecutándose.

Siguiente capítulo

Mini-reto: conversor de unidades con reglas y precisión

Arrow Right Icon
Portada de libro electrónico gratuitaPython desde cero con mini-retos: aprende programando (sin teoría eterna)
58%

Python desde cero con mini-retos: aprende programando (sin teoría eterna)

Nuevo curso

12 páginas

Descarga la aplicación para obtener una certificación gratuita y escuchar cursos en segundo plano, incluso con la pantalla apagada.