Assert en Python con ejemplo de uso

Una aserción es una comprobación de sanidad para asegurarse de que su código no está haciendo algo obviamente incorrecto. Estas comprobaciones de sanidad se realizan mediante sentencias assert. Si la comprobación de sanidad falla, entonces se lanza una excepción AssertionError. En código, una sentencia assert consiste en lo siguiente:

  • La palabra clave assert
  • Una condición (es decir, una expresión que se evalúa como True o False )
  • una coma
  • Una cadena para mostrar cuando la condición es False

En lenguaje sencillo, una sentencia assert dice: «Afirmo que la condición es verdadera, y si no, hay un error en alguna parte, así que detenga inmediatamente el programa». Por ejemplo, introduzca lo siguiente en el shell interactivo:

>>> ages = [26, 57, 92, 54, 22, 15, 17, 80, 47, 73]
>>> ages.sort()
>>> ages
[15, 17, 22, 26, 47, 54, 57, 73, 80, 92]
>>> assert
ages[0] <= ages[-1] # Assert that the first age is <= the last age.

La declaración de assert aquí afirma que el primer elemento en ages debe ser menor o igual que el último. Este es un control de cordura; si el código en sort() está libre de errores e hizo su trabajo, entonces la afirmación sería verdadera.

Debido a que la expresión ages[0] <= ages[-1] se evalúa como True , la declaración de assert no hace nada.

Sin embargo, supongamos que tenemos un error en nuestro código. Digamos que accidentalmente llamamos al método de lista reverse() en lugar del método de lista sort(). Cuando ingresamos lo siguiente en el shell interactivo, la declaración assert genera un AssertionError :

>>> ages = [26, 57, 92, 54, 22, 15, 17, 80, 47, 73]
>>> ages.reverse()
>>> ages
[73, 47, 80, 17, 15, 22, 54, 92, 57, 26]
>>> assert ages[0] <= ages[-1] # Assert that the first age is <= the last age.
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AssertionError

A diferencia de las excepciones, su código no debe manejar assert con try y except; si un assert falla, su programa debería fallar. Al «fallar rápido» de esta manera, acorta el tiempo entre la causa original del error y el momento en que lo nota por primera vez. Esto reducirá la cantidad de código que tendrá que verificar antes de encontrar la causa del error.

Las aserciones son para errores del programador, no errores del usuario. Las aserciones solo deben fallar mientras el programa está en desarrollo; un usuario nunca debería ver un error de aserción en un programa terminado. Para los errores que su programa puede encontrar como una parte normal de su funcionamiento (como un archivo que no se encuentra o que el usuario ingresa datos no válidos), genere una excepción en lugar de detectarla con una aserciones. No debe usar aserciones en lugar de generar excepciones, porque los usuarios pueden optar por desactivar las afirmaciones. Si ejecuta un script de Python con python -O myscript.py en lugar de python myscript.py, Python omitirá las declaraciones assert. Los usuarios pueden deshabilitar las aserciones cuando están desarrollando un programa y necesitan ejecutarlo en una configuración de producción que requiere un rendimiento máximo. (Aunque, en muchos casos, dejarán las aserciones habilitadas incluso entonces).

Las aserciones tampoco reemplazan las pruebas exhaustivas. Por ejemplo, si el ejemplo anterior de edades se estableció en [10, 3, 2, 1, 20], entonces la aserción de afirmar ages[0] <= ages[-1] no notaría que la lista no estaba ordenada, porque casualmente tenía una primera edad que era menor o igual que la última edad, que es lo único que verificó la afirmación.

Digamos que estás construyendo un programa de simulación de semáforos. La estructura de datos que representa los semáforos en una intersección es un diccionario con claves 'ns' y 'ew', para los semáforos orientados de norte a sur y de este a oeste, respectivamente. Los valores de estas claves serán una de las cadenas 'green', 'yellow' o 'red'. El código sería algo así

market_2nd = {'ns': 'green', 'ew': 'red'}
mission_16th = {'ns': 'red', 'ew': 'green'}

Estas dos variables serán para las intersecciones de Market Street and 2nd Street, y Mission Street and 16th Street. Para comenzar el proyecto, usted quiere escribir una función switchLights(), que tomará un diccionario de intersección como argumento y cambiará las luces.

Al principio, podría pensar que switchLights() debería simplemente cambiar cada luz al siguiente color de la secuencia: Cualquier valor 'green' debería cambiar a 'yellow', los valores 'yellow' deberían cambiar a 'red', y los valores 'red' deberían cambiar a 'green'. El código para implementar esta idea podría ser así:

def switchLights(stoplight):
    for key in stoplight.keys():
        if stoplight[key] == 'green':
            stoplight[key] = 'yellow'
        elif stoplight[key] == 'yellow':
            stoplight[key] = 'red'
        elif stoplight[key] == 'red':
            stoplight[key] = 'green'

switchLights(market_2nd)

Es posible que ya vea el problema con este código, pero supongamos que escribió el resto del código de simulación, miles de líneas, sin darse cuenta. Cuando finalmente ejecuta la simulación, el programa no falla, ¡pero sus autos virtuales sí!

Como ya escribió el resto del programa, no tiene idea de dónde podría estar el error. Tal vez esté en el código que simula los autos o en el código que simula los conductores virtuales. Podría llevar horas rastrear el error hasta la función switchLights().

Pero si mientras escribía switchLights() hubiera agregado un asserts para verificar que al menos una de las luces esté siempre en rojo, podría haber incluido lo siguiente en la parte inferior de la función:

assert 'red' in stoplight.values(), 'Neither light is red! ' + str(stoplight)

Con este assert en su lugar, su programa fallaría con este mensaje de error:

   Traceback (most recent call last):
     File "carSim.py", line 14, in <module>
       switchLights(market_2nd)
     File "carSim.py", line 13, in switchLights
       assert 'red' in stoplight.values(), 'Neither light is red! ' +
   str(stoplight)
➊ AssertionError: Neither light is red! {'ns': 'yellow', 'ew': 'green'}

La línea importante aquí es AssertionError ➊ . Si bien el bloqueo de su programa no es ideal, inmediatamente señala que falló una verificación de sanidad: ninguna dirección del tráfico tiene una luz roja, lo que significa que el tráfico podría ir en ambos sentidos. Al fallar rápidamente al principio de la ejecución del programa, puede ahorrarse mucho esfuerzo de depuración en el futuro.

Deja una respuesta