Propagación de errores (raise)
Cuando
se produce algún tipo de error, se puede actuar de muchas formas, según
el caso. Se puede informar al usuario mediante algún mensaje, se puede
mostrar información del contexto en el que se produjo, el tipo de error,
etc. para que otro programador lo tenga en cuenta si tiene que
modificar o corregir el programa o...
... Se puede hacer que, si la excepción se produjo dentro de la llamada a una función, el error se propague al código que realizó la llamada. Sería algo así como "pasarle el marrón" a quien lo produjo. Por ejemplo, en el siguiente código, el método raise serviría para informar de forma "personalizada" que al dividir entre cero se ha producido un error de división.
... Se puede hacer que, si la excepción se produjo dentro de la llamada a una función, el error se propague al código que realizó la llamada. Sería algo así como "pasarle el marrón" a quien lo produjo. Por ejemplo, en el siguiente código, el método raise serviría para informar de forma "personalizada" que al dividir entre cero se ha producido un error de división.
# *-* coding:utf-8 *-* def divide(dividendo, divisor): try: resultado = dividendo/divisor return resultado except ZeroDivisionError: raise ZeroDivisionError("El divisor no puede ser cero") divisor = int(raw_input("Divisor (escribe cero): ")) dividendo = int(raw_input("Dividendo: ")) print divide(dividendo, divisor)
= = =
Quizás quede más claro en el siguiente ejemplo...- El programa principal llama a la función f
- En la función f se llama a la función g
- En g, se llama la h.
- En h se levanta una excepción ValueError.
- Esta excepción vuelve a g.
- Esta excepción retorna a f
- Y en f ya se retorna, imprimiendo el texto que se le dio en la función h.
# *-* coding:utf-8 *-* # Función F def f(): try: g() except ValueError, detalle: print "Caught a ValueError:", detalle.message #Función G def g(): h() # Función H def h(): raise ValueError('Esta es una prueba.') # Programa principal f()
= = =
Validaciones
Las
validaciones son técnicas de programación defensiva, que intentan
comprobar sobre todo pre-condiciones en las funciones, y devolver
información valiosa si no se cumplen.
Se usan par comprobar el tipo de un
dato, si está dentro de un determinado rango (o dominio) o que el dato
tenga una determinada característica. La validación tiene que informar
convenientemente del error. En cualquier caso, lo importante es que el
resultado generado por nuestro código cuando funciona correctamente y el
resultado generado cuando falla debe ser claramente distinto.
Comprobaciones de dominio o rango, o de contenido
Intentamos que información externa, entregada por el usuario o recuperada de un fichero, sea adecuada, o bien porque pueda dudarse de que lo sea o no. No siempre es fácil. Por ejemplo:# *-* coding: utf-8 *-* def raiz(n): """ pre: acepta un número mayor que cero post: devuelve un número que es la raíz cuadrada. """ assert n>=0, "No puedo aceptar valores negativos" resultado = n ** (0.5) return resultado valor = int(raw_input("Valor a calcular la raíz cuadrada: ")) print raiz(valor)
= = =
Validando datos del usuario
No podemos suponer que los usuarios introduzcan correctamente los datos. Es, pues, deseable programar para evitar circunstancias como estas# *-* coding: utf-8 *-* def raiz(n): """ pre: acepta un número mayor que cero post: devuelve un número que es la raíz cuadrada. """ assert n>=0, "No puedo aceptar valores negativos" resultado = n ** (0.5) return resultado def leer_dato(): """ post: Debe ingresar un número entero. Al usuario se le pedirá un número entero de forma indefinida. """ while True: valor = raw_input("Valor a calcular la raíz cuadrada: ") try: valor = int(valor) return valor except ValueError: print "ATENCIÓN: Debe ingresar un número entero." valor = leer_dato() print raiz(valor)Y un ejemplo en el que sólo se deja al usuario introducir el dato un número limitado de veces.
... def leer_dato(): """ post: Debe ingresar un número entero. Al usuario se le pedirá un número entero una cantidad de veces limitada. """ t = 1 while t<=3: valor = raw_input("Valor a calcular la raíz cuadrada: ") try: valor = int(valor) return valor except ValueError: t += 1 raise ValueError, "No has introducido un dato numérico" ...
= = =
Comprobaciones de tipo
Para comprobar si una variable es de un tipo determinado se utiliza la función type, que devuelve el tipo de datos (entero, float, cadena, etc.) de la variable.
if type(i) != int: raise TypeError, "i debe ser del tipo int"Si el tipo de datos no es entero, se propaga un error.
Si el tipo de datos se quisiera comprobar que pertenece a más de un tipo puede hacerse
if type(i) not in (int, float, long, complex): raise TypeError, "i debe ser numérico"O, incluso mejor
if not isinstance(i, (int, float, long, complex) ): raise TypeError, "i debe ser numérico"
= = =
Comprobaciones de características
No entraremos en muchos detalles. Simplemente saber que la función hasattr(variable, función) vale true si a la variable se le puede aplicar la función (por ejemplo, si variable es un número, entonces se le puede aplicar una función numérica, pero si es de cadena no).
= = =
No hay comentarios:
Publicar un comentario