Respuestas:
La assert
declaración existe en casi todos los lenguajes de programación. Ayuda a detectar problemas temprano en su programa, donde la causa es clara, y no más tarde como un efecto secundario de alguna otra operación.
Cuando tu lo hagas...
assert condition
... le está diciendo al programa que pruebe esa condición e inmediatamente active un error si la condición es falsa.
En Python, es más o menos equivalente a esto:
if not condition:
raise AssertionError()
Pruébelo en el shell de Python:
>>> assert True # nothing happens
>>> assert False
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AssertionError
Las aserciones pueden incluir un mensaje opcional, y puede deshabilitarlas al ejecutar el intérprete.
Para imprimir un mensaje si la afirmación falla:
assert False, "Oh no! This assertion failed!"
No , no utilizar paréntesis para llamar assert
como una función. Es una declaración. Si lo haces assert(condition, message)
, estarás ejecutando assert
con una (condition, message)
tupla como primer parámetro.
En cuanto a deshabilitarlos, cuando se ejecuta python
en modo optimizado, donde __debug__
está False
, las declaraciones de aserción serán ignoradas. Solo pasa la -O
bandera:
python -O script.py
Vea aquí para la documentación relevante.
if not condition: raise AssertError()
, ¿por qué debería usar afirmar? ¿Hay alguna condición bajo la cual la if not condition
afirmación sea mejor además de ser una forma más corta de declaración?
if
). Lea los documentos para obtener más información :)
assert
, pero después de leer todas las respuestas, no obtuve nada que quiero!
Cuidado con los paréntesis. Como se ha señalado anteriormente, en Python 3, assert
sigue siendo una declaración , por analogía con print(..)
, uno puede extrapolar lo mismo assert(..)
ao raise(..)
pero no debería.
Esto es importante porque:
assert(2 + 2 == 5, "Houston we've got a problem")
no funcionará, a diferencia de
assert 2 + 2 == 5, "Houston we've got a problem"
La razón por la que el primero no funcionará es porque se bool( (False, "Houston we've got a problem") )
evalúa True
.
En la declaración assert(False)
, estos son solo paréntesis redundantes False
, que evalúan su contenido. Pero con assert(False,)
los paréntesis ahora son una tupla, y una tupla no vacía se evalúa True
en un contexto booleano.
assert (2 + 2 = 5), "Houston we've got a problem"
debería estar bien, ¿sí?
assert (2 + 2 = 5), "Houston we've got a problem"
no funcionará ... pero no tiene nada que ver con la declaración de aserción, lo cual está bien. Su condición no funcionará porque no es una condición. Perder un segundo =
.
Como han señalado otras respuestas, assert
es similar a lanzar una excepción si una condición dada no es verdadera. Una diferencia importante es que las declaraciones de aserción se ignoran si compila su código con la opción de optimización -O
. La documentación dice que assert expression
puede describirse mejor como equivalente a
if __debug__:
if not expression: raise AssertionError
Esto puede ser útil si desea probar a fondo su código, luego lanzar una versión optimizada cuando esté satisfecho de que ninguno de sus casos de afirmación falle: cuando la optimización está activada, la __debug__
variable se convierte en False y las condiciones dejarán de evaluarse. Esta característica también puede atraparte si confías en las afirmaciones y no te das cuenta de que han desaparecido.
if Not Error: raise Exception(“ this is a error”)
? De esa manera, el programa seguirá mostrando la fuente del error, cuando el usuario lo ejecute ..
assert
declaración? La suposición aquí es que cuando el programa se lanza al usuario final, está utilizando el indicador -O, suponiendo que se han eliminado todos los errores. Por lo tanto, cualquier error o bloqueo del programa se debe a la entrada al programa que es válida según el contrato, pero no puede ser manejada por el programa. Por lo tanto, debe alertar al usuario como tal.
El objetivo de una afirmación en Python es informar a los desarrolladores sobre errores irrecuperables en un programa.
Las afirmaciones no pretenden indicar condiciones de error esperadas, como "archivo no encontrado", donde un usuario puede tomar medidas correctivas (o simplemente intentarlo de nuevo).
Otra forma de verlo es decir que las aserciones son autocomprobaciones internas en su código. Funcionan declarando algunas condiciones como imposibles en su código. Si estas condiciones no se cumplen, significa que hay un error en el programa.
Si su programa está libre de errores, estas condiciones nunca ocurrirán. Pero si uno de ellos lo hace aparecer el programa se bloquea con un error de aserción que le dice exactamente lo que se desencadenó condición de “imposible”. Esto hace que sea mucho más fácil rastrear y corregir errores en sus programas.
Aquí hay un resumen de un tutorial sobre las afirmaciones de Python que escribí:
La declaración de afirmación de Python es una ayuda de depuración, no un mecanismo para manejar errores de tiempo de ejecución. El objetivo de usar aserciones es permitir que los desarrolladores encuentren la causa raíz probable de un error más rápidamente. Nunca se debe generar un error de aserción a menos que haya un error en su programa.
assert
declaración y cuándo usar esto. Estoy tratando de entender una serie de términos que introdujo en el artículo.
assert store.product_exists(product_id), 'Unknown product id'
no es una buena práctica, porque si la depuración está desactivada, user
incluso si no admin
se podrá eliminar el producto. ¿Lo consideras assert user.is_admin()
como un unrecoverable
error? ¿Por qué esto no es un self-check
?
assert statement
, ¿no price
puede considerarse también una entrada del usuario? ¿Por qué consideras assert user.is_admin()
como validación de datos pero no assert price
?
Otros ya le han dado enlaces a la documentación.
Puede probar lo siguiente en un shell interactivo:
>>> assert 5 > 2
>>> assert 2 > 5
Traceback (most recent call last):
File "<string>", line 1, in <fragment>
builtins.AssertionError:
La primera declaración no hace nada, mientras que la segunda plantea una excepción. Esta es la primera pista: las afirmaciones son útiles para verificar las condiciones que deberían ser ciertas en una posición dada de su código (generalmente, el principio (condiciones previas) y el final de una función (condiciones posteriores)).
Las afirmaciones en realidad están muy ligadas a la programación por contrato, lo cual es una práctica de ingeniería muy útil:
De documentos:
Assert statements are a convenient way to insert debugging assertions into a program
Aquí puede leer más: http://docs.python.org/release/2.5.2/ref/assert.html
La afirmación tiene dos formas.
La forma simple assert <expression>
, es equivalente a
if __debug__:
if not <expression>: raise AssertionError
La forma extendida assert <expression1>, <expression2>
, es equivalente a
if __debug__:
if not <expression1>: raise AssertionError, <expression2>
Las afirmaciones son una forma sistemática de verificar que el estado interno de un programa es el esperado por el programador, con el objetivo de detectar errores. Vea el ejemplo a continuación.
>>> number = input('Enter a positive number:')
Enter a positive number:-1
>>> assert (number > 0), 'Only positive numbers are allowed!'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AssertionError: Only positive numbers are allowed!
>>>
Aquí hay un ejemplo simple, guarde esto en un archivo (digamos b.py)
def chkassert(num):
assert type(num) == int
chkassert('a')
y el resultado cuando $python b.py
Traceback (most recent call last):
File "b.py", line 5, in <module>
chkassert('a')
File "b.py", line 2, in chkassert
assert type(num) == int
AssertionError
si la declaración después de afirmar es verdadera, el programa continúa, pero si la declaración después de afirmar es falsa, entonces el programa da un error. Simple como eso.
p.ej:
assert 1>0 #normal execution
assert 0>1 #Traceback (most recent call last):
#File "<pyshell#11>", line 1, in <module>
#assert 0>1
#AssertionError
La assert
declaración existe en casi todos los lenguajes de programación. Ayuda a detectar problemas temprano en su programa, donde la causa es clara, y no más tarde como un efecto secundario de alguna otra operación. Siempre esperan una True
condición.
Cuando haces algo como:
assert condition
Le está diciendo al programa que pruebe esa condición e inmediatamente active un error si es falso.
En Python, assert
expresión , es equivalente a:
if __debug__:
if not <expression>: raise AssertionError
Puede usar la expresión extendida para pasar un mensaje opcional :
if __debug__:
if not (expression_1): raise AssertionError(expression_2)
Pruébelo en el intérprete de Python:
>>> assert True # Nothing happens because the condition returns a True value.
>>> assert False # A traceback is triggered because this evaluation did not yield an expected value.
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AssertionError
Hay algunas advertencias para ver antes de usarlas principalmente para aquellos que consideran alternar entre las declaraciones assert
y if
. El objetivo de usar assert
es en ocasiones cuando el programa verifica una condición y devuelve un valor que debería detener el programa de inmediato en lugar de tomar alguna forma alternativa para evitar el error:
Como habrás notado, la assert
declaración usa dos condiciones. Por lo tanto, no use paréntesis para englobarlos como un consejo obvio. Si haces tal como:
assert (condition, message)
Ejemplo:
>>> assert (1==2, 1==1)
<stdin>:1: SyntaxWarning: assertion is always true, perhaps remove parentheses?
Ejecutará el assert
con un (condition, message)
que representa una tupla como primer parámetro, y esto sucede porque la tupla no vacía en Python siempreTrue
es así . Sin embargo, puede hacerlo por separado sin problema:
assert (condition), "message"
Ejemplo:
>>> assert (1==2), ("This condition returns a %s value.") % "False"
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AssertionError: This condition returns a False value.
Si se pregunta cuándo usar la assert
declaración. Tome un ejemplo usado en la vida real:
* Cuando su programa tiende a controlar cada parámetro ingresado por el usuario o cualquier otra cosa:
def loremipsum(**kwargs):
kwargs.pop('bar') # return 0 if "bar" isn't in parameter
kwargs.setdefault('foo', type(self)) # returns `type(self)` value by default
assert (len(kwargs) == 0), "unrecognized parameter passed in %s" % ', '.join(kwargs.keys())
* Otro caso es en matemáticas cuando 0 o no positivo como coeficiente o constante en una ecuación determinada:
def discount(item, percent):
price = int(item['price'] * (1.0 - percent))
print(price)
assert (0 <= price <= item['price']),\
"Discounted prices cannot be lower than 0 "\
"and they cannot be higher than the original price."
return price
* o incluso un simple ejemplo de implementación booleana:
def true(a, b):
assert (a == b), "False"
return 1
def false(a, b):
assert (a != b), "True"
return 0
La mayor importancia es no confiar en la assert
declaración para ejecutar el procesamiento de datos o la validación de datos, ya que esta declaración se puede desactivar en la inicialización de Python con -O
o -OO
flag, es decir, el valor 1, 2 y 0 (por defecto), respectivamente, o PYTHONOPTIMIZE
la variable de entorno .
Valor 1:
* las afirmaciones están deshabilitadas;
* los archivos de bytecode se generan usando la .pyo
extensión en lugar de .pyc
;
* sys.flags.optimize
se establece en 1 ( True
);
* y, __debug__
se establece en False
;
Valor 2: deshabilita una cosa más
* las cadenas de documentos están deshabilitadas;
Por lo tanto, usar la assert
declaración para validar un tipo de datos esperados es extremadamente peligroso, lo que implica incluso algunos problemas de seguridad. Entonces, si necesita validar algún permiso, le recomiendo en su raise AuthError
lugar. Como precondicional efectivo, los assert
programadores usan comúnmente un en bibliotecas o módulos que no tienen un usuario que interactúe directamente.
Como se resume de manera concisa en C2 Wiki :
Una aserción es una expresión booleana en un punto específico de un programa que será verdadera a menos que haya un error en el programa.
Puede usar una assert
declaración para documentar su comprensión del código en un punto particular del programa. Por ejemplo, puede documentar supuestos o garantías sobre entradas (condiciones previas), estado del programa (invariantes) o salidas (condiciones posteriores).
Si alguna vez falla su afirmación, esta es una alerta para usted (o su sucesor) de que su comprensión del programa era incorrecta cuando lo escribió y que probablemente contenga un error.
Para obtener más información, John Regehr tiene una maravillosa publicación de blog sobre el uso de aserciones , que también se aplica a la assert
declaración de Python .
Python afirmar es básicamente una ayuda de depuración que prueba la condición para la autocomprobación interna de su código. Assert hace que la depuración sea realmente fácil cuando su código entra en casos extremos imposibles. Afirma verificar esos casos imposibles.
Digamos que hay una función para calcular el precio del artículo después del descuento:
def calculate_discount(price, discount):
discounted_price = price - [discount*price]
assert 0 <= discounted_price <= price
return discounted_price
aquí, precio_descontado nunca puede ser menor que 0 y mayor que el precio real. Por lo tanto, en caso de que se viole la condición anterior, la afirmación genera un Error de aserción, que ayuda al desarrollador a identificar que algo imposible ha sucedido.
Espero eso ayude :)
assert
es útil en un contexto de depuración, pero no debe confiarse fuera de un contexto de depuración.
Mi breve explicación es:
assert
se eleva AssertionError
si la expresión es falsa, de lo contrario solo continúa el código, y si hay una coma sea lo que sea AssertionError: whatever after comma
, y codificar es como:raise AssertionError(whatever after comma)
Un tutorial relacionado sobre esto:
https://www.tutorialspoint.com/python/assertions_in_python.htm
assert
, pero no cuándo usar (o no usar) un assert
; También señala que un assert
puede ser desactivado si __debug__
es False
útil.
En Pycharm, si usa assert
junto con isinstance
para declarar el tipo de un objeto, le permitirá acceder a los métodos y atributos del objeto principal mientras está codificando, se completará automáticamente.
Por ejemplo, digamos que self.object1.object2
es un MyClass
objeto.
import MyClasss
def code_it(self):
testObject = self.object1.object2 # at this point, program doesn't know that testObject is a MyClass object yet
assert isinstance(testObject , MyClasss) # now the program knows testObject is a MyClass object
testObject.do_it() # from this point on, PyCharm will be able to auto-complete when you are working on testObject
Como está escrito en otras respuestas, las assert
declaraciones se utilizan para verificar el estado del programa en un punto dado.
No repetiré lo que se dijo sobre el mensaje asociado, paréntesis u -O
opción y __debug__
constante. Consulte también el documento para obtener información de primera mano. Me centraré en su pregunta: ¿de qué sirve assert
? Más precisamente, ¿cuándo (y cuándo no) se debe usar assert
?
Las assert
declaraciones son útiles para depurar un programa, pero se desaconseja verificar la entrada del usuario. Utilizo la siguiente regla general: mantener las aserciones para detectar una situación que no debería suceder . Una entrada del usuario puede ser incorrecta, por ejemplo, una contraseña demasiado corta, pero esto no es un caso que no debería ocurrir . Si el diámetro de un círculo no es dos veces mayor que su radio, está en un caso que no debería suceder .
El uso más interesante, en mi opinión, assert
está inspirado en la
programación por contrato según lo descrito por B. Meyer en [Construcción de software orientada a objetos] (
https://www.eiffel.org/doc/eiffel/Object-Oriented_Software_Construction% 2C_2nd_Edition
) e implementado en el [lenguaje de programación Eiffel] (
https://en.wikipedia.org/wiki/Eiffel_(programming_language) ). No puede emular completamente la programación por contrato utilizando la assert
declaración, pero es interesante mantener la intención.
Aquí hay un ejemplo. Imagine que tiene que escribir una head
función (como la [ head
función en Haskell] (
http://www.zvon.org/other/haskell/Outputprelude/head_f.html )). La especificación que se le da es: "si la lista no está vacía, devuelva el primer elemento de una lista". Mira las siguientes implementaciones:
>>> def head1(xs): return xs[0]
Y
>>> def head2(xs):
... if len(xs) > 0:
... return xs[0]
... else:
... return None
(Sí, esto se puede escribir como return xs[0] if xs else None
, pero ese no es el punto) .
Si la lista no está vacía, ambas funciones tienen el mismo resultado y este resultado es correcto:
>>> head1([1, 2, 3]) == head2([1, 2, 3]) == 1
True
Por lo tanto, ambas implementaciones son (espero) correctas. Se diferencian cuando intenta tomar el elemento principal de una lista vacía:
>>> head1([])
Traceback (most recent call last):
...
IndexError: list index out of range
Pero:
>>> head2([]) is None
True
Nuevamente, ambas implementaciones son correctas, porque nadie debería pasar una lista vacía a estas funciones (estamos fuera de la especificación ). Esa es una llamada incorrecta, pero si hace una llamada así, puede pasar cualquier cosa. Una función genera una excepción, la otra devuelve un valor especial. Lo más importante es: no podemos confiar en este comportamiento . Si xs
está vacío, esto funcionará:
print(head2(xs))
Pero esto bloqueará el programa:
print(head1(xs))
Para evitar algunas sorpresas, me gustaría saber cuándo estoy pasando algún argumento inesperado a una función. En otras palabras: me gustaría saber cuándo el comportamiento observable no es confiable, porque depende de la implementación, no de la especificación. Por supuesto, puedo leer la especificación, pero los programadores no siempre leen con cuidado los documentos.
Imagínese si tuviera una forma de insertar la especificación en el código para obtener el siguiente efecto: cuando violo la especificación, por ejemplo, al pasar una lista vacía a head
, recibo una advertencia. Sería de gran ayuda escribir un programa correcto (es decir, que cumpla con la especificación). Y ahí es donde assert
entra en escena:
>>> def head1(xs):
... assert len(xs) > 0, "The list must not be empty"
... return xs[0]
Y
>>> def head2(xs):
... assert len(xs) > 0, "The list must not be empty"
... if len(xs) > 0:
... return xs[0]
... else:
... return None
Ahora tenemos:
>>> head1([])
Traceback (most recent call last):
...
AssertionError: The list must not be empty
Y:
>>> head2([])
Traceback (most recent call last):
...
AssertionError: The list must not be empty
Tenga en cuenta que head1
arroja un AssertionError
, no un IndexError
. Eso es importante porque AssertionError
no es un error de tiempo de ejecución: indica una violación de la especificación. Quería una advertencia, pero recibo un error. Afortunadamente, puedo desactivar el cheque (usando la -O
opción), pero bajo mi propio riesgo. Lo haré, un choque es realmente costoso, y espero lo mejor. Imagine que mi programa está incrustado en una nave espacial que viaja a través de un agujero negro. Desactivaré las afirmaciones y espero que el programa sea lo suficientemente robusto como para no bloquearse el mayor tiempo posible.
Este ejemplo fue solo sobre condiciones previas, ya que puede usarlas assert
para verificar las condiciones posteriores (el valor de retorno y / o el estado) y las invariantes (estado de una clase). Tenga en cuenta que verificar las condiciones posteriores y las invariantes con assert
puede ser engorroso:
No tendrá algo tan sofisticado como Eiffel, pero puede mejorar la calidad general de un programa.
Para resumir, la assert
declaración es una forma conveniente de detectar una situación que no debería suceder . Las violaciones de la especificación (por ejemplo, pasar una lista vacía a head
) son de primera clase, esto no debería suceder en situaciones. Por lo tanto, aunque la assert
declaración se puede usar para detectar cualquier situación inesperada, es una forma privilegiada de garantizar que se cumpla la especificación. Una vez que haya insertado assert
declaraciones en el código para representar la especificación, podemos esperar que haya mejorado la calidad del programa porque se informarán argumentos incorrectos, valores de retorno incorrectos, estados incorrectos de una clase ...
formato: afirmar Expresión [, argumentos] Cuando afirmar encuentra una declaración, Python evalúa la expresión. Si la declaración no es verdadera, se genera una excepción (aserciónError). Si la aserción falla, Python usa ArgumentExpression como argumento para AssertionError. Las excepciones AssertionError pueden detectarse y manejarse como cualquier otra excepción utilizando la instrucción try-except, pero si no se manejan, terminarán el programa y producirán un rastreo. Ejemplo:
def KelvinToFahrenheit(Temperature):
assert (Temperature >= 0),"Colder than absolute zero!"
return ((Temperature-273)*1.8)+32
print KelvinToFahrenheit(273)
print int(KelvinToFahrenheit(505.78))
print KelvinToFahrenheit(-5)
Cuando se ejecuta el código anterior, produce el siguiente resultado:
32.0
451
Traceback (most recent call last):
File "test.py", line 9, in <module>
print KelvinToFahrenheit(-5)
File "test.py", line 4, in KelvinToFahrenheit
assert (Temperature >= 0),"Colder than absolute zero!"
AssertionError: Colder than absolute zero!
def getUser(self, id, Email):
user_key = id and id or Email
assert user_key
Se puede usar para garantizar que los parámetros se pasen en la llamada de función.
if not user_key: raise ValueError()
últimos 2 párrafos de verificación aquí: wiki.python.org/moin/UsingAssertionsEffectively
assert
no debe usarse para la validación de entrada porque la validación se eliminará si __debug__
es así False
. Además, el uso de aserciones para fines que no sean de depuración puede hacer que las personas capturen los correos AssertionError
electrónicos resultantes , lo que puede hacer que la depuración sea más difícil en lugar de menos.
>>>this_is_very_complex_function_result = 9
>>>c = this_is_very_complex_function_result
>>>test_us = (c < 4)
>>> #first we try without assert
>>>if test_us == True:
print("YES! I am right!")
else:
print("I am Wrong, but the program still RUNS!")
I am Wrong, but the program still RUNS!
>>> #now we try with assert
>>> assert test_us
Traceback (most recent call last):
File "<pyshell#52>", line 1, in <module>
assert test_us
AssertionError
>>>
Básicamente, el significado de la palabra clave afirmar es que si la condición no es verdadera, entonces a través de un error de aserción, de lo contrario, continuará, por ejemplo, en Python.
código-1
a=5
b=6
assert a==b
SALIDA:
assert a==b
AssertionError
código-2
a=5
b=5
assert a==b
SALIDA:
Process finished with exit code 0
assert
, pero no responde cuándo usar (o no usar) un assert
.