Saltar a contenido

Ejercitación aplicada
Excepciones

  1. Supongamos que a lo largo de nuestra trabajo profesional como programador, una de nuestras principales tareas es obtener números del usuario con bastante frecuencia.

    Sería bueno inventar una función propia que se encargue de esta tarea. Incluso para que luego la podamos compartir con otros programadores.

    ¿Cómo podríamos resolver este programa?

    Recuerda que una función devuelve siempre un valor (resultado) y no solamente imprimir algo en pantalla como lo hace una subrutina (este efecto recibe el nombre de side effect o efecto secundario dentro de un programa).

    Cómo usarías la función?

    Escribe un programa que defina la función obtener_numero_entero() que solicite un valor al usuario y lo convierta a un número entero. Dicha función deberá manejar el error si el valor ingresado no puede ser convertido a un número entero. Y devolver el número entero ingresado por el usuario cuando este si pueda ser convertido. Esta es una manera de abstraer la noción de obtener un número entero (encapsular la lógica para que nada por afuera de la función necesite saber cómo se obtiene un número entero. Ese es trabajo exclusivo de la función).

    Además, implementa la función main() que utilice la función obtener_numero_entero para solicitar al usuario un número entero y luego imprima el número ingresado. Cuando esté implementada esta función, verás que con esta abstracción, el código es más limpio y fácil de entender.

    Haz clic aquí para ver la solución propuesta
    Python
    # Define la función main()
    def main():
        # Solicita al usuario un número entero y lo almacena en la variable numero
        numero = obtener_numero_entero()
        print(f"El número ingresado es: {numero}")
    
    # Define la función obtener_numero_entero()
    def obtener_numero_entero():
        while True:
            try:
                numero = int(input("Ingrese un número entero: "))
            except ValueError:
                print("¡Ups! El valor ingresado no es un número entero.")
            else:
                break
        return numero
    
    # Llama a la función main()
    main()
    

    Ejecutamos el programa con un valor numérico:

    Terminal (Entrada/Salida)
    Ingrese un número entero: 5
    El número ingresado es: 5
    _
    

    Ahora ejecutamos el programa con un valor no numérico:

    Terminal (Entrada/Salida)
    Ingrese un número entero: hola
    ¡Ups! El valor ingresado no es un número entero.
    Ingrese un número entero: 3
    El número ingresado es: 3
    _
    

    Se define la función main() que solicita al usuario un número entero y lo almacena en la variable numero utilizando la función obtener_numero_entero(). Luego, imprime el número ingresado.

    Se define la función obtener_numero_entero() que solicita al usuario un número entero y lo convierte a un número entero. Si el valor ingresado no puede ser convertido a un número entero, se maneja el error y se vuelve a solicitar el ingreso del número. Una vez que el usuario ingresa un número entero, se rompe el bucle while con el comando break y se devuelve el número ingresado.

    En la primera ejecución, la salida en la Terminal (Entrada/Salida) es "Ingrese un número entero: 5" y "El número ingresado es: 5", ya que se ingresó el número 5 y se imprimió el número ingresado.

    En la segunda ejecución, lLa salida en la Terminal (Entrada/Salida) es "Ingrese un número entero: hola", "¡Ups! El valor ingresado no es un número entero.", "Ingrese un número entero: 3" y "El número ingresado es: 3", ya que se ingresó el valor no numérico "hola" y luego el número 3, y se imprimió el número ingresado.


  2. Dada la solución propuesta en el ejercicio anterior, el desafío es refactorizar el programa para que la función obtener_numero_entero() esté más comprimida.

    Es decir, elimina los bloques y variables innecesarias para que la función sea más eficiente (aunque tal vez resulte menos legible y sea más críptica) y más corta en términos de líneas de código.

    Haz clic aquí para ver la solución propuesta
    Python
    # Define la función main()
    def main():
        # Solicita al usuario un número entero y lo almacena en la variable numero
        numero = obtener_numero_entero()
        print(f"El número ingresado es: {numero}")
    
    # Define la función obtener_numero_entero()
    def obtener_numero_entero():
        while True:
            try:
                return int(input("Ingrese un número entero: "))
            except ValueError:
                print("¡Ups! El valor ingresado no es un número entero.")
    
    # Llama a la función main()
    main()
    

    Hemos eliminado el bloque else junto con el comando break; la instrucción final return numero; y la variable numero que ha sido reemplaza directamente por el comando return.

    Ahora, la función obtener_numero_entero() es más compacta y devuelve directamente el número entero ingresado por el usuario cuando este si pueda ser convertido. Si el valor ingresado no puede ser convertido a un número entero, se maneja el error y se vuelve a solicitar el ingreso del número hasta que este sea válido.

    ¡Para recordar!

    El comando break se utiliza para salir de un bucle.

    El comando return se utiliza para devolver un valor de una función.

    Y aunque break y return son comandos que ejecutan tareas diferentes, en este caso, return se utiliza para salir del bucle while cuando el usuario ingresa un número entero válido, además de salir de la función al retornar el valor correspondiente. Cumple ambas tareas. Así, no es necesario utilizar break en este caso.

    ¡Para recordar!

    ¿Por qué definir una variable en una línea para ser utilizada solamente en la línea siguiente y luego nunca más?

    No crees variables de manera innecesaria. El hacerlo no solo te obligará a tener más líneas de código, sino que además es un gasto innecesario de uso de recursos de la computadora, la memoria RAM y el procesador.

    Aquí es donde pueden aparecer diferentes criterios. Por un lado, estamos reforzando el código. Estamos usando menos líneas. Es más fácil de leer y hay menos probabilidades de que haya cometido un error.

    Por otro lado, el código críptico y compacto es más complicado de entender.

    Independientemente del criterio que adoptes, lo importante es que lo hagas conscientemente. Que puedas justificar por qué has eliges determinado criterio y no que sea una cuestión al azar o fortuita. Tal vez hoy te resulte difícil de entender o de elegir, pero con la práctica y la experiencia, te resultará más sencillo.


  3. Ahora que ya sabes como solicitar el ingreso de un número entero y manejar los posibles errores, escribe un programa que defina una función que sirva para solicitar el ingreso de cualquier tipo de dato.

    La función deberá llamarse obtener_dato() y deberá ser capaz de mostrar un mensaje específico al usuario (puedes usar una variable llamada prompt para tal fin), solicitar el ingreso de un dato y devolverlo convertido en el tipo de dato que corresponda (también deberá ser pasada esta indicación a través de una variable llamada tipo_de_dato).

    Además, implementa la función main() que le pregunte al usuario que tipo de dato quiere ingresar y luego llame a la función obtener_dato() con los argumentos necesarios para que esta pueda realizar la tarea correspondiente.

    Haz clic aquí para ver la solución propuesta
    Python
    # Define la función main()
    def main():
        # Solicita al usuario el tipo de dato que quiere ingresar
        tipo_de_dato = input("¿Qué tipo de dato desea ingresar? (int, float, str): ")
        # Solicita al usuario el dato y lo almacena en la variable dato
        dato = obtener_dato(tipo_de_dato, "Ingrese un dato: ")
        print(f"El dato ingresado es: {dato}")
    
    # Define la función obtener_dato()
    def obtener_dato(tipo_de_dato, prompt):
        while True:
            try:
                return eval(f"{tipo_de_dato}(input(prompt))")
            except ValueError:
                print("¡Ups! El valor ingresado no es un dato válido.")
    
    # Llama a la función main()
    main()
    

    Ejecutamos el programa con un valor numérico:

    Terminal (Entrada/Salida)
    ¿Qué tipo de dato desea ingresar? (int, float, str): int
    Ingrese un dato: 5
    El dato ingresado es: 5
    _
    

    Ahora ejecutamos el programa con un valor no numérico:

    Terminal (Entrada/Salida)
    ¿Qué tipo de dato desea ingresar? (int, float, str): int
    Ingrese un dato: hola
    ¡Ups! El valor ingresado no es un dato válido.
    Ingrese un dato: 3
    El dato ingresado es: 3
    _
    

    Se define la función main() que le pregunta al usuario que tipo de dato quiere ingresar y luego llama a la función obtener_dato() con los argumentos necesarios para que esta pueda realizar la tarea correspondiente. Luego, imprime el dato ingresado.

    Se define la función obtener_dato() que solicita al usuario el ingreso de un dato y lo convierte al tipo de dato que corresponda. Si el valor ingresado no puede ser convertido al tipo de dato correspondiente, se maneja el error y se vuelve a solicitar el ingreso del dato hasta que este sea válido.