Red de conocimiento informático - Problemas con los teléfonos móviles - Cuándo usar aserciones en Python

Cuándo usar aserciones en Python

La pregunta es cómo usar expresiones de aserción en ciertos escenarios y, por lo general, la gente las usa mal, así que decidí escribir un artículo sobre cuándo usar aserciones y cuándo no.

Para aquellos que aún no lo saben, la afirmación de Python se usa para verificar una condición y, si es verdadera, no hacer nada. Si es falso, se genera un AssertError con un mensaje de error. Por ejemplo:

py> x = 23

py> afirmar x > 0, "x no es cero ni negativo"

py> afirmar x%2 = = 0, "x no es un número par"

Rastreo (última llamada más reciente):

Archivo "", línea 1, en

AssertionError : x no es un número par

Mucha gente utiliza la afirmación como una forma muy rápida y sencilla de generar una excepción cuando el argumento es incorrecto, pero esto está mal, muy mal, por dos razones. Primero, AssertError no es un error que deba generarse al probar parámetros. No deberías escribir código como este:

if not isinstance(x, int):

raise AssertionError("not int")

Deberías lanzar TypeError es incorrecto y afirmar arrojará una excepción incorrecta.

Pero, lo que es más peligroso, afirmar tiene un problema molesto: puede compilarse y luego nunca ejecutarse si usa la opción -O o -oo

para ejecutar Python, el resultado no garantiza que se ejecutará la expresión de afirmación. Cuando se usa de manera apropiada, esto es el futuro, pero cuando se usa de manera inapropiada, hará que el código se rompa cuando se ejecute con

-O.

Entonces, ¿cuándo deberías usar afirmar? No existen reglas específicas, afirmar debe usarse para:

Programación defensiva

Verificar la lógica del programa en tiempo de ejecución

Verificar convenciones

Programas Constantes

Consulte la documentación

(También es aceptable usar afirmar al probar el código, es una forma muy conveniente de realizar pruebas unitarias y puede aceptar estas pruebas cuando usa -O El tiempo de ejecución de banderas no hace nada. A veces uso

Assertion False en mi código para marcar ramas de código no escritas que quiero que fallen (aunque podría ser mejor lanzar NotImplementedError).

Hay muchas opiniones sobre las aserciones porque garantizan la exactitud de su código. Si está seguro de que su código es correcto, no es necesario utilizar aserciones porque nunca fallarán y puede simplemente eliminarlas. estás seguro de que la verificación fallará, el código se compilará e ignorará tu verificación si no usas aserciones.

En ambos casos, cuando estás relativamente seguro del código, pero es muy interesante cuando. no estás absolutamente seguro y es posible que te pierdas algunas situaciones realmente extrañas, en cuyo caso las comprobaciones de tiempo de ejecución adicionales pueden ayudarte a detectar cualquier error a tiempo.

Otra buena forma de utilizar aserciones es verificar que sea una invariante. es un valor de verdad en el que debe confiar a menos que un error haga que sea falso. Si algo sale mal, es mejor detectarlo temprano para probarlo, pero no queremos ralentizar el código. Utilice aserciones porque se pueden activar durante el desarrollo y desactivar durante la producción.

Un ejemplo de una no variable podría ser si su función espera una conexión a la base de datos cuando se inicia y promete mantener la conexión cuando regresa, esta sería una función no variable:

Python

def some_function(arg):

afirmar no DB.

...# El código termina aquí

afirmar no DB.closed()

devolver resultado

La afirmación en sí es un buen comentario y es mejor que si escribes la afirmación directamente:

# Cuando llegamos a En este punto, sabemos que n > 2

Puedes asegurar esto agregando una aserción:

assert n > 2

Las afirmaciones también son una forma de programación defensiva. En lugar de hacer que su código se proteja contra errores ahora, es mejor evitar que ocurran errores después de modificar el código. Idealmente, las pruebas unitarias harían este tipo de trabajo, pero la realidad es que estas pruebas a menudo no lo hacen. Es posible que las personas se olviden de ejecutar el código de prueba antes de comprometerse. Las comprobaciones internas son otra línea de defensa contra los errores, especialmente aquellos que no son obvios pero hacen que el código falle y devuelva resultados incorrectos.

Un bloque de unión con algunas declaraciones if...elif y usted sabe que debe haber algún valor antes de esto:

Se espera que # objetivo sea uno de x, y o z uno, pero no el otro.

if objetivo == x:

run_x_code()

elif objetivo == y:

run_y_code()

else:

run_z_code()

Supongamos que el código ahora es completamente correcto. ¿Pero será siempre cierto? Se modifican las dependencias y también el código. ¿Qué sucede si la dependencia se modifica a target = w? Si modificamos el código pero no aquí, podría resultar en una llamada incorrecta a la función run_z_code

y arrojar un error. Sería mejor si el código pudiera escribirse de forma defensiva para que se ejecute correctamente, o que el error se ejecute inmediatamente incluso si el código se cambia en el futuro.

Los comentarios al principio del código son un buen paso, pero a menudo las personas son demasiado perezosas para leer o actualizar estos comentarios. Una vez que esto sucede, la anotación se vuelve inútil. Pero con las aserciones, puedo documentar simultáneamente las suposiciones sobre un bloque de código y desencadenar errores limpios cuando se violan esas suposiciones

assert target in (x, y, z)

if target == x:

run_x_code()

elif objetivo == y:<

run_y_code()

else:

afirmar objetivo == z

run_z_code()

De esta manera, las aserciones son tanto una forma de programación defensiva como una forma de documentación. Pensé en un programa mejor:

if target == x:

run_x_code()

elif target == y:

run_y_code()

elif target == z:

run_z_code()<

else:

# Esta situación siempre no lo hará suceder. Pero, ¿qué pasa si...

rise RuntimeError("Se produjo un error inesperado")

El diseño convencional es otro buen uso de las aserciones.

Suponemos que existe un contrato entre la función y la persona que llama, por ejemplo:

"Si me pasas una cadena que no está vacía, prometo pasar la primera letra de esa cadena y escribirla en mayúscula".

Si una función o llamada infringe esta convención, el código se romperá. Suponiendo que la función tiene algunas condiciones previas y posteriores, la función se escribiría así:

def first_upper(astring):

afirmar isinstance(astring, str) y len(astring) > 0

resultado = astring[0].upper()

afirmar isinstance(resultado, cadena) y len(resultado) == 1

afirmar resultado == result.upper()

return result

Diseñado convencionalmente con el objetivo de una programación correcta, es necesario mantener las condiciones previas y posteriores. Este es un caso de uso clásico para las afirmaciones porque una vez que lanzamos el código sin problemas a producción, el programa será correcto y podremos eliminar la verificación de forma segura.

Los siguientes son escenarios recomendados donde no se deben usar aserciones:

No use aserciones para probar datos proporcionados por el usuario

No use aserciones para verificar que Crees que hay cosas que pueden salir mal durante el uso normal del programa. Las afirmaciones se utilizan para comprobar problemas muy raros. Sus usuarios no deberían ver ningún error de aserción; si lo ven, es un error, corríjalo.

En algunos casos, las aserciones no se utilizarán porque son más cortas que la verificación exacta, y esta no debería ser una forma para que los programadores perezosos se salgan con la suya.

No lo utilice para comprobar los parámetros de entrada de una biblioteca pública, ya que no tiene control sobre la persona que llama y, por lo tanto, no garantiza que la persona que llama infrinja el acuerdo entre las partes.

No utilices afirmaciones para errores que creas que se pueden recuperar. En otras palabras, no realice cambios sólo para detectar errores de aserción en el código de producción.

No utilices demasiadas afirmaciones para evitar que el código sea oscuro.