Réponses:
L' assert
instruction existe dans presque tous les langages de programmation. Il permet de détecter les problèmes au début de votre programme, où la cause est claire, plutôt que plus tard comme effet secondaire d'une autre opération.
Quand vous le faites ...
assert condition
... vous dites au programme de tester cette condition et de déclencher immédiatement une erreur si la condition est fausse.
En Python, c'est à peu près équivalent à ceci:
if not condition:
raise AssertionError()
Essayez-le dans le shell Python:
>>> assert True # nothing happens
>>> assert False
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AssertionError
Les assertions peuvent inclure un message facultatif et vous pouvez les désactiver lors de l'exécution de l'interpréteur.
Pour imprimer un message si l'assertion échoue:
assert False, "Oh no! This assertion failed!"
N'utilisez pas de parenthèses pour appeler assert
comme une fonction. C'est une déclaration. Si vous le faites, assert(condition, message)
vous exécuterez le assert
avec un (condition, message)
tuple comme premier paramètre.
Quant à les désactiver, lors de l'exécution python
en mode optimisé, où __debug__
est False
, les instructions assert seront ignorées. Passez juste le -O
drapeau:
python -O script.py
Voir ici pour la documentation pertinente.
if not condition: raise AssertError()
, pourquoi devrais-je utiliser assert? Existe-t-il des conditions dans lesquelles l'affirmation est meilleure autre que le simple fait d'être une forme de if not condition
déclaration plus courte ?
if
). Lisez la documentation pour plus d'informations :)
assert
, mais après avoir lu toutes les réponses, je n'ai absolument rien que je veux!
Attention aux parenthèses. Comme cela a été souligné ci-dessus, en Python 3, assert
est toujours une déclaration , donc par analogie avec print(..)
, on peut extrapoler la même chose à assert(..)
ou raise(..)
mais vous ne devriez pas.
Ceci est important car:
assert(2 + 2 == 5, "Houston we've got a problem")
ne fonctionnera pas, contrairement à
assert 2 + 2 == 5, "Houston we've got a problem"
La raison pour laquelle le premier ne fonctionnera pas est qu'il bool( (False, "Houston we've got a problem") )
évalue True
.
Dans l'instruction assert(False)
, ce ne sont que des parenthèses redondantes False
, qui évaluent leur contenu. Mais avec assert(False,)
les parenthèses sont maintenant un tuple, et un tuple non vide est évalué True
dans un contexte booléen.
assert (2 + 2 = 5), "Houston we've got a problem"
ça devrait aller, oui?
assert (2 + 2 = 5), "Houston we've got a problem"
ne fonctionnera pas ... mais cela n'a rien à voir avec la déclaration assert, ce qui est bien. Votre condition ne fonctionnera pas car ce n'est pas une condition. Manquant une seconde =
.
Comme d'autres réponses l'ont noté, cela assert
revient à lancer une exception si une condition donnée n'est pas vraie. Une différence importante est que les instructions assert sont ignorées si vous compilez votre code avec l'option d'optimisation -O
. La documentation dit que cela assert expression
peut mieux être décrit comme étant équivalent à
if __debug__:
if not expression: raise AssertionError
Cela peut être utile si vous souhaitez tester soigneusement votre code, puis publier une version optimisée lorsque vous êtes satisfait qu'aucun de vos cas d'assertion échoue - lorsque l'optimisation est activée, la __debug__
variable devient False et les conditions cessent d'être évaluées. Cette fonctionnalité peut également vous rattraper si vous comptez sur les assertions et ne réalisez pas qu'elles ont disparu.
if Not Error: raise Exception(“ this is a error”)
? De cette façon, le programme affichera toujours la source de l'erreur, lorsque l'utilisateur l'exécutera.
assert
instruction? L'hypothèse ici est que lorsque le programme est remis à l'utilisateur final, vous utilisez l'indicateur -O, supposant ainsi que tous les bogues ont été supprimés. Par conséquent, toute erreur ou panne de programme est due à une entrée dans le programme qui est valide selon le contrat, mais ne peut pas être gérée par le programme. Il devrait donc alerter l'utilisateur en tant que tel.
Le but d'une assertion en Python est d'informer les développeurs sur les erreurs irrécupérables dans un programme.
Les assertions ne sont pas destinées à signaler des conditions d'erreur attendues, comme «fichier introuvable», où un utilisateur peut prendre des mesures correctives (ou simplement réessayer).
Une autre façon de voir les choses est de dire que les assertions sont des auto-contrôles internes dans votre code. Ils fonctionnent en déclarant certaines conditions impossibles dans votre code. Si ces conditions ne tiennent pas, cela signifie qu'il y a un bogue dans le programme.
Si votre programme est exempt de bogues, ces conditions ne se produiront jamais. Mais si l' un d'eux ne fait que se produit le programme plantera avec une erreur d'assertion vous dire exactement quelle condition « impossible » a été déclenchée. Cela facilite grandement la recherche et la correction des bogues dans vos programmes.
Voici un résumé d' un tutoriel sur les assertions de Python que j'ai écrites:
L'instruction assert de Python est une aide au débogage, pas un mécanisme de gestion des erreurs d'exécution. L'objectif des assertions est de permettre aux développeurs de trouver plus rapidement la cause probable d'un bogue. Une erreur d'assertion ne doit jamais être déclenchée sauf s'il y a un bogue dans votre programme.
assert
déclaration et quand l'utiliser. J'essaie de comprendre un certain nombre de termes que vous avez introduits dans l'article.
assert store.product_exists(product_id), 'Unknown product id'
n'est pas une bonne pratique, car si le débogage est désactivé, le user
même sinon un admin
pourra supprimer le produit. Considérez-vous assert user.is_admin()
comme une unrecoverable
erreur? Pourquoi est-ce pas un self-check
?
assert statement
, ne peut- price
il pas également être considéré comme une entrée utilisateur? Pourquoi considérez-vous assert user.is_admin()
que la validation des données mais pas assert price
?
D'autres vous ont déjà donné des liens vers la documentation.
Vous pouvez essayer ce qui suit dans un shell interactif:
>>> assert 5 > 2
>>> assert 2 > 5
Traceback (most recent call last):
File "<string>", line 1, in <fragment>
builtins.AssertionError:
La première déclaration ne fait rien, tandis que la seconde soulève une exception. C'est le premier indice: les assertions sont utiles pour vérifier les conditions qui devraient être vraies à une position donnée de votre code (généralement, le début (conditions préalables) et la fin d'une fonction (postconditions)).
Les assertions sont en fait fortement liées à la programmation par contrat, ce qui est une pratique d'ingénierie très utile:
Depuis les documents:
Assert statements are a convenient way to insert debugging assertions into a program
Ici, vous pouvez en savoir plus: http://docs.python.org/release/2.5.2/ref/assert.html
Les assertions sont un moyen systématique de vérifier que l'état interne d'un programme est celui attendu par le programmeur, dans le but de détecter les bogues. Voir l'exemple ci-dessous.
>>> 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!
>>>
Voici un exemple simple, enregistrez-le dans un fichier (disons b.py)
def chkassert(num):
assert type(num) == int
chkassert('a')
et le résultat quand $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 l'instruction après assertion est vraie, le programme continue, mais si l'instruction après assertion est fausse, le programme donne une erreur. Aussi simple que cela.
par exemple:
assert 1>0 #normal execution
assert 0>1 #Traceback (most recent call last):
#File "<pyshell#11>", line 1, in <module>
#assert 0>1
#AssertionError
L' assert
instruction existe dans presque tous les langages de programmation. Il permet de détecter les problèmes au début de votre programme, où la cause est claire, plutôt que plus tard comme effet secondaire d'une autre opération. Ils attendent toujours une True
condition.
Lorsque vous faites quelque chose comme:
assert condition
Vous dites au programme de tester cette condition et de déclencher immédiatement une erreur si elle est fausse.
En Python, l' assert
expression est équivalente à:
if __debug__:
if not <expression>: raise AssertionError
Vous pouvez utiliser l'expression étendue pour transmettre un message facultatif :
if __debug__:
if not (expression_1): raise AssertionError(expression_2)
Essayez-le dans l'interpréteur 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
Il y a quelques mises en garde à voir avant de les utiliser principalement pour ceux qui jugent basculer entre les déclarations assert
et if
. Le but d'utiliserassert
est parfois lorsque le programme vérifie une condition et renvoie une valeur qui devrait arrêter le programme immédiatement au lieu de prendre une autre manière de contourner l'erreur:
Comme vous l'avez peut-être remarqué, l' assert
instruction utilise deux conditions. Par conséquent, n'utilisez pas de parenthèses pour les englober comme un conseil évident. Si vous faites comme:
assert (condition, message)
Exemple:
>>> assert (1==2, 1==1)
<stdin>:1: SyntaxWarning: assertion is always true, perhaps remove parentheses?
Vous exécuterez le assert
avec un (condition, message)
qui représente un tuple comme premier paramètre, et cela se produit car le tuple non vide en Python l'est toujoursTrue
. Cependant, vous pouvez le faire séparément sans problème:
assert (condition), "message"
Exemple:
>>> 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 vous vous demandez quand utiliser la assert
déclaration. Prenons un exemple utilisé dans la vie réelle:
* Lorsque votre programme a tendance à contrôler chaque paramètre entré par l'utilisateur ou autre:
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())
* Un autre cas concerne les mathématiques lorsque 0 ou non positif comme coefficient ou constante sur une certaine équation:
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
* ou même un simple exemple d'implémentation booléenne:
def true(a, b):
assert (a == b), "False"
return 1
def false(a, b):
assert (a != b), "True"
return 0
La plus grande importance est de ne pas compter sur l' assert
instruction pour exécuter le traitement ou la validation des données car cette instruction peut être désactivée lors de l'initialisation Python avec -O
ou -OO
indicateur - ce qui signifie la valeur 1, 2 et 0 (par défaut), respectivement - ouPYTHONOPTIMIZE
la variable d'environnement .
Valeur 1:
* les assertions sont désactivées;
* les fichiers de bytecode sont générés en utilisant l' .pyo
extension au lieu de .pyc
;
* sys.flags.optimize
est défini sur 1 ( True
);
* et, __debug__
est défini sur False
;
Valeur 2: désactive une autre chose
* les docstrings sont désactivées;
Par conséquent, l'utilisation de l' assert
instruction pour valider une sorte de données attendues est extrêmement dangereuse, impliquant même certains problèmes de sécurité. Ensuite, si vous devez valider une autorisation, je vous recommande raise AuthError
plutôt. En tant qu'effet préalable, an assert
est couramment utilisé par les programmeurs sur des bibliothèques ou des modules qui n'ont pas d'interaction directe avec un utilisateur.
Comme résumé brièvement sur le C2 Wiki :
Une assertion est une expression booléenne à un point spécifique d'un programme qui sera vraie à moins qu'il n'y ait un bogue dans le programme.
Vous pouvez utiliser une assert
instruction pour documenter votre compréhension du code à un point de programme particulier. Par exemple, vous pouvez documenter des hypothèses ou des garanties sur les entrées (préconditions), l'état du programme (invariants) ou les sorties (postconditions).
Si votre affirmation échoue, il s'agit d'une alerte pour vous (ou votre successeur) que votre compréhension du programme était erronée lorsque vous l'avez écrit et qu'il contient probablement un bogue.
Pour plus d'informations, John Regehr a un merveilleux article de blog sur l' utilisation des assertions , qui s'applique également à la assert
déclaration Python .
Python assert est fondamentalement une aide au débogage qui teste la condition pour l'auto-vérification interne de votre code. Assert facilite le débogage lorsque votre code se retrouve dans des cas extrêmes impossibles. Affirmez vérifier ces cas impossibles.
Disons qu'il existe une fonction pour calculer le prix de l'article après remise:
def calculate_discount(price, discount):
discounted_price = price - [discount*price]
assert 0 <= discounted_price <= price
return discounted_price
ici, discounted_price ne peut jamais être inférieur à 0 et supérieur au prix réel. Donc, dans le cas où la condition ci-dessus n'est pas respectée, assert soulève une erreur d'assertion, ce qui aide le développeur à identifier que quelque chose d'impossible s'est produit.
J'espère que cela aide :)
assert
est utile dans un contexte de débogage, mais ne doit pas être invoqué en dehors d'un contexte de débogage.
Ma courte explication est:
assert
déclenche AssertionError
si expression est fausse, sinon continue simplement le code, et s'il y a une virgule quoi que ce soit AssertionError: whatever after comma
, et coder est comme:raise AssertionError(whatever after comma)
Un tutoriel connexe à ce sujet:
https://www.tutorialspoint.com/python/assertions_in_python.htm
assert
, mais pas quand utiliser (ou ne pas utiliser) un assert
; notant également qu'un an assert
peut être désactivé s'il __debug__
est False
utile.
Dans Pycharm, si vous utilisez assert
avec isinstance
pour déclarer le type d'un objet, il vous permettra d'accéder aux méthodes et aux attributs de l'objet parent pendant que vous codez, il se complétera automatiquement automatiquement.
Par exemple, disons self.object1.object2
est un MyClass
objet.
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
Comme assert
indiqué dans d'autres réponses, les instructions sont utilisées pour vérifier l'état du programme à un moment donné.
Je ne répéterai pas ce qui a été dit sur le message associé, les parenthèses ou l' -O
option et la __debug__
constante. Consultez également le doc pour des informations de première main. Je vais me concentrer sur votre question: à quoi ça sert assert
? Plus précisément, quand (et quand non) faut-il utiliser assert
?
Les assert
instructions sont utiles pour déboguer un programme, mais déconseillées pour vérifier les entrées utilisateur. J'utilise la règle empirique suivante: conserver les assertions pour détecter une situation qui ne devrait pas se produire . Une entrée utilisateur peut être incorrecte, par exemple un mot de passe trop court, mais ce n'est pas un cas qui ne devrait pas se produire . Si le diamètre d'un cercle n'est pas deux fois plus grand que son rayon, vous êtes dans un tel cas ne devrait pas se produire .
L'utilisation la plus intéressante, selon moi, assert
est inspirée de la
programmation par contrat telle que décrite par B. Meyer dans [Object-Oriented Software Construction] (
https://www.eiffel.org/doc/eiffel/Object-Oriented_Software_Construction% 2C_2nd_Edition
) et implémenté dans le [langage de programmation Eiffel] (
https://en.wikipedia.org/wiki/Eiffel_(programming_language) ). Vous ne pouvez pas émuler complètement la programmation par contrat en utilisant l' assert
instruction, mais il est intéressant de garder l'intention.
Voici un exemple. Imaginez que vous deviez écrire une head
fonction (comme la [ head
fonction dans Haskell] (
http://www.zvon.org/other/haskell/Outputprelude/head_f.html )). La spécification qui vous est donnée est: "si la liste n'est pas vide, retournez le premier élément d'une liste". Regardez les implémentations suivantes:
>>> def head1(xs): return xs[0]
Et
>>> def head2(xs):
... if len(xs) > 0:
... return xs[0]
... else:
... return None
(Oui, cela peut s'écrire return xs[0] if xs else None
, mais ce n'est pas le but) .
Si la liste n'est pas vide, les deux fonctions ont le même résultat et ce résultat est correct:
>>> head1([1, 2, 3]) == head2([1, 2, 3]) == 1
True
Par conséquent, les deux implémentations sont (j'espère) correctes. Ils diffèrent lorsque vous essayez de prendre l'élément de tête d'une liste vide:
>>> head1([])
Traceback (most recent call last):
...
IndexError: list index out of range
Mais:
>>> head2([]) is None
True
Encore une fois, les deux implémentations sont correctes, car personne ne doit passer une liste vide à ces fonctions (nous sommes hors spécification ). C'est un appel incorrect, mais si vous faites un tel appel, tout peut arriver. Une fonction déclenche une exception, l'autre renvoie une valeur spéciale. Le plus important est: nous ne pouvons pas compter sur ce comportement . Si xs
est vide, cela fonctionnera:
print(head2(xs))
Mais cela fera planter le programme:
print(head1(xs))
Pour éviter quelques surprises, je voudrais savoir quand je passe un argument inattendu à une fonction. En d'autres termes: je voudrais savoir quand le comportement observable n'est pas fiable, car cela dépend de l'implémentation, pas de la spécification. Bien sûr, je peux lire les spécifications, mais les programmeurs ne lisent pas toujours attentivement les documents.
Imaginez si j'avais un moyen d'insérer la spécification dans le code pour obtenir l'effet suivant: lorsque je viole la spécification, par exemple en passant une liste vide à head
, j'obtiens un avertissement. Ce serait une grande aide pour écrire un programme correct (c'est-à-dire conforme aux spécifications). Et c'est là assert
qu'entre en scène:
>>> def head1(xs):
... assert len(xs) > 0, "The list must not be empty"
... return xs[0]
Et
>>> def head2(xs):
... assert len(xs) > 0, "The list must not be empty"
... if len(xs) > 0:
... return xs[0]
... else:
... return None
Maintenant nous avons:
>>> head1([])
Traceback (most recent call last):
...
AssertionError: The list must not be empty
Et:
>>> head2([])
Traceback (most recent call last):
...
AssertionError: The list must not be empty
Notez que head1
jette un AssertionError
, pas un IndexError
. Cela est important parce qu'un AssertionError
n'est pas une erreur d'exécution: il signale une violation de la spécification. Je voulais un avertissement, mais j'obtiens une erreur. Heureusement, je peux désactiver la vérification (en utilisant l' -O
option), mais à mes risques et périls. Je vais le faire un crash est vraiment cher, et j'espère pour le mieux. Imaginez que mon programme soit intégré dans un vaisseau spatial qui traverse un trou noir. Je désactiverai les assertions et j'espère que le programme est suffisamment robuste pour ne pas planter aussi longtemps que possible.
Cet exemple ne concernait que les conditions préalables, que vous pouvez utiliser assert
pour vérifier les postconditions (la valeur de retour et / ou l'état) et les invariants (état d'une classe). Notez que la vérification des postconditions et des invariants avec assert
peut être fastidieuse:
Vous n'aurez pas quelque chose d'aussi sophistiqué qu'Eiffel, mais vous pouvez cependant améliorer la qualité globale d'un programme.
Pour résumer, la assert
déclaration est un moyen pratique de détecter une situation qui ne devrait pas se produire . Les violations de la spécification (par exemple en passant une liste vide à head
) sont de première classe, cela ne devrait pas se produire . Par conséquent, bien que l' assert
instruction puisse être utilisée pour détecter toute situation inattendue, c'est un moyen privilégié de s'assurer que la spécification est remplie. Une fois que vous avez inséré des assert
instructions dans le code pour représenter la spécification, nous pouvons espérer que vous avez amélioré la qualité du programme car des arguments incorrects, des valeurs de retour incorrectes, des états incorrects d'une classe ... seront signalés.
format: assert Expression [, arguments] Lorsque assert rencontre une instruction, Python évalue l'expression. Si l'instruction n'est pas vraie, une exception est levée (assertionError). Si l'assertion échoue, Python utilise ArgumentExpression comme argument pour AssertionError. Les exceptions AssertionError peuvent être interceptées et gérées comme n'importe quelle autre exception à l'aide de l'instruction try-except, mais si elles ne sont pas gérées, elles termineront le programme et produiront une trace. Exemple:
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)
Lorsque le code ci-dessus est exécuté, il produit le résultat suivant:
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
Peut être utilisé pour garantir que les paramètres sont passés dans l'appel de fonction.
if not user_key: raise ValueError()
2 derniers paragraphes ici: wiki.python.org/moin/UsingAssertionsEffectively
assert
ne doit pas être utilisé pour la validation d'entrée , car soit la validation sera dépouillé si __debug__
est False
. L'utilisation d'assertions à des fins non déboguées peut également amener les utilisateurs à intercepter les AssertionError
s résultants , ce qui peut rendre le débogage plus difficile au lieu de moins.
>>>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
>>>
Fondamentalement, le mot clé assert signifie que si la condition n'est pas vraie, elle passe par une erreur d'assertion, sinon elle continue par exemple en python.
code-1
a=5
b=6
assert a==b
PRODUCTION:
assert a==b
AssertionError
code-2
a=5
b=5
assert a==b
PRODUCTION:
Process finished with exit code 0
assert
, mais ne répond pas quand utiliser (ou ne pas utiliser) un assert
.