Existe-t-il un problème de performances ou de maintenance du code lors de l'utilisation
assert
dans le cadre du code standard au lieu de l'utiliser uniquement à des fins de débogage?Est
assert x >= 0, 'x is less than zero'
mieux ou pire que
if x < 0: raise Exception, 'x is less than zero'
De plus, existe-t-il un moyen de définir une règle métier comme
if x < 0 raise error
celle-ci est toujours vérifiée sans letry/except/finally
so, si à tout moment dans le codex
est inférieur à 0, une erreur est déclenchée, comme si vous définissezassert x < 0
au début d'une fonction, n'importe où dans la fonction oùx
devient inférieur à 0, une exception est levée?
483
assert
.Réponses:
Pour pouvoir lancer automatiquement une erreur lorsque x devient inférieur à zéro dans toute la fonction. Vous pouvez utiliser des descripteurs de classe . Voici un exemple:
la source
Les assertions doivent être utilisées pour tester des conditions qui ne devraient jamais se produire . Le but est de planter tôt dans le cas d'un état de programme corrompu.
Les exceptions doivent être utilisées pour les erreurs qui peuvent se produire, et vous devez presque toujours créer vos propres classes d'exceptions .
Par exemple, si vous écrivez une fonction pour lire à partir d'un fichier de configuration dans un
dict
, une mise en forme incorrecte dans le fichier devrait générer unConfigurationSyntaxError
, alors que vous le pouvezassert
, vous n'êtes pas sur le point de revenirNone
.Dans votre exemple, si
x
une valeur est définie via une interface utilisateur ou à partir d'une source externe, une exception est préférable.Si
x
n'est défini que par votre propre code dans le même programme, utilisez une assertion.la source
assert
contient un impliciteif __debug__
et peut être optimisé - comme l' indique la réponse de John MeeLes instructions "assert" sont supprimées lorsque la compilation est optimisée . Donc, oui, il y a des différences de performances et de fonctionnalités.
Si vous utilisez
assert
pour implémenter des fonctionnalités d'application, puis optimisez le déploiement en production, vous serez en proie à des défauts "mais cela fonctionne en développement".Voir PYTHONOPTIMIZE et -O -OO
la source
raise
un à laException
place. Oh - je viens de découvrir un bien nomméSuspiciousOperation
Exception
avec des sous-classesDjango
! Parfait!bandit
votre code, il vous en avertira.Les quatre objectifs de
assert
Supposons que vous travaillez sur 200 000 lignes de code avec quatre collègues Alice, Bernd, Carl et Daphne. Ils appellent votre code, vous appelez leur code.
Puis
assert
a quatre rôles :Informez Alice, Bernd, Carl et Daphne de ce que votre code attend.
Supposons que vous ayez une méthode qui traite une liste de tuples et que la logique du programme puisse se casser si ces tuples ne sont pas immuables:
C'est plus fiable que des informations équivalentes dans la documentation et beaucoup plus facile à maintenir.
Informez l'ordinateur de ce que votre code attend.
assert
applique le bon comportement des appelants de votre code. Si votre code appelle le code d'Alices et de Bernd appelle le vôtre, alors sans leassert
, si le programme plante dans le code d'Alices, Bernd pourrait supposer que c'était la faute d'Alice, Alice enquêterait et pourrait supposer que c'était votre faute, vous enquêtez et dites à Bernd que c'était en fait le sien. Beaucoup de travail perdu.Avec les assertions, quiconque se trompe, il pourra rapidement voir que c'est de sa faute, pas de la vôtre. Alice, Bernd et vous en bénéficiez tous. Économise d'immenses quantités de temps.
Informez les lecteurs de votre code (y compris vous-même) de ce que votre code a réalisé à un moment donné.
Supposons que vous ayez une liste d'entrées et que chacune d'elles puisse être propre (ce qui est bien) ou qu'elle puisse être smorsh, trale, gullup ou twinkled (qui ne sont pas toutes acceptables). Si c'est smorsh, il doit être non smorshed; si c'est vrai, il faut le balancer; si c'est du goéland, il doit être trotté (et peut-être aussi arpenté aussi); s'il est scintillant, il doit être scintillé à nouveau, sauf le jeudi. Vous voyez l'idée: c'est compliqué. Mais le résultat final est (ou devrait être) que toutes les entrées sont propres. La bonne chose à faire est de résumer l'effet de votre boucle de nettoyage comme
Ces déclarations sauvent un casse-tête pour tous ceux qui essaient de comprendre exactement ce que la merveilleuse boucle réalise. Et le plus fréquent de ces personnes sera probablement vous-même.
Informez l'ordinateur de ce que votre code a réalisé à un moment donné.
Si jamais vous oubliez de suivre une entrée qui en a besoin après le trot,
assert
cela vous sauvera la journée et évitera que votre code casse le cher Daphné beaucoup plus tard.À mon avis,
assert
les deux objectifs de la documentation (1 et 3) et de la sauvegarde (2 et 4) sont tout aussi précieux.Informer les gens peut même être plus utile que d'informer l'ordinateur car cela peut éviter les erreurs mêmes que les
assert
objectifs doivent attraper (dans le cas 1) et de nombreuses erreurs subséquentes dans tous les cas.la source
En plus des autres réponses, les assertions lèvent elles-mêmes des exceptions, mais seulement AssertionErrors. D'un point de vue utilitaire, les assertions ne conviennent pas lorsque vous avez besoin d'un contrôle de grain fin sur les exceptions que vous interceptez.
la source
AssertionErrors
, lorsque vous êtes d'accord avec le fait qu'elle soit à grain grossier. En réalité, vous ne devriez pas les attraper.La seule chose qui ne va vraiment pas avec cette approche est qu'il est difficile de faire une exception très descriptive en utilisant des instructions assert. Si vous recherchez une syntaxe plus simple, n'oubliez pas que vous pouvez également faire quelque chose comme ceci:
Un autre problème est que l'utilisation de l'assertion pour la vérification de condition normale rend difficile la désactivation des assertions de débogage à l'aide de l'indicateur -O.
la source
Le mot anglais affirmer ici est utilisé dans le sens de jurer , affirmer , avouer . Cela ne signifie pas "vérifier" ou "devrait être" . Cela signifie que vous, en tant que codeur, faites une déclaration sous serment ici:
Si le code est correct, sauf bouleversements à événement unique , pannes matérielles et autres, aucune assertion n'échouera jamais . C'est pourquoi le comportement du programme envers un utilisateur final ne doit pas être affecté. Surtout, une assertion ne peut pas échouer même dans des conditions programmatiques exceptionnelles . Cela n'arrive jamais. Si cela se produit, le programmeur doit être zappé pour cela.
la source
Comme cela a été dit précédemment, les assertions doivent être utilisées lorsque votre code NE DEVRAIT JAMAIS atteindre un point, ce qui signifie qu'il y a un bogue. La raison la plus utile que je peux voir pour utiliser une assertion est probablement un invariant / pré / postcondition. Il s'agit de quelque chose qui doit être vrai au début ou à la fin de chaque itération d'une boucle ou d'une fonction.
Par exemple, une fonction récursive (2 fonctions distinctes, donc 1 gère les mauvaises entrées et les autres gère le mauvais code, car il est difficile de distinguer avec la récursivité). Cela rendrait évident si j'avais oublié d'écrire la déclaration if, ce qui avait mal tourné.
Ces invariants de boucle peuvent souvent être représentés par une assertion.
la source
#precondition: n >= 0
et une affirmation, il peut simplement écrire@precondition(lambda n: n >= 0)
__doc__
attribut en donnant une chaîne supplémentaireY a-t- il un problème de performances?
N'oubliez pas de "le faire fonctionner avant de le faire fonctionner rapidement" .
Très peu de pour cent de n'importe quel programme sont généralement pertinents pour sa vitesse. Vous pouvez toujours expulser ou simplifier un
assert
si cela s'avérait être un problème de performances - et la plupart d'entre eux ne le seront jamais.Soyez pragmatique :
supposez que vous disposez d'une méthode qui traite une liste non vide de tuples et la logique du programme se brisera si ces tuples ne sont pas immuables. Vous devez écrire:
C'est probablement bien si vos listes ont généralement dix entrées, mais cela peut devenir un problème si elles contiennent un million d'entrées. Mais plutôt que de jeter entièrement ce précieux chèque, vous pouvez simplement le rétrograder en
ce qui est bon marché mais va probablement attraper la plupart des erreurs de programme réelles de toute façon.
la source
assert(len(listOfTuples)==0 or type(listOfTyples[0])==tuple)
.Eh bien, c'est une question ouverte, et j'ai deux aspects que je veux aborder: quand ajouter des assertions et comment écrire les messages d'erreur.
Objectif
Pour l'expliquer à un débutant - les assertions sont des déclarations qui peuvent soulever des erreurs, mais vous ne les attraperez pas. Et ils ne devraient normalement pas être élevés, mais dans la vraie vie, ils le sont parfois de toute façon. Et c'est une situation grave, dont le code ne peut pas récupérer, ce que nous appelons une «erreur fatale».
Ensuite, c'est à des fins de débogage qui, bien que correctes, semblent très dédaigneuses. J'aime mieux la formulation `` déclarant les invariants, qui ne devraient jamais être violés '', même si cela fonctionne différemment selon les débutants ... ou même contrôler le flux avec elle.
Style
En Python,
assert
c'est une instruction, pas une fonction! (rappelezassert(False, 'is true')
- vous ne soulèvera pas. Mais, ayant cela à l'écart:Quand et comment écrire le «message d'erreur» facultatif?
Cela s'applique en fait aux frameworks de tests unitaires, qui ont souvent de nombreuses méthodes dédiées pour faire des assertions (
assertTrue(condition)
,assertFalse(condition), assertEqual(actual, expected)
etc.). Ils fournissent souvent également un moyen de commenter l'assertion.Dans le code jetable, vous pouvez vous passer des messages d'erreur.
Dans certains cas, il n'y a rien à ajouter à l'affirmation:
def dump (quelque chose): assert isinstance (quelque chose, Dumpable) # ...
Mais à part cela, un message est utile pour la communication avec d'autres programmeurs (qui sont parfois des utilisateurs interactifs de votre code, par exemple dans Ipython / Jupyter, etc.).
Donnez-leur des informations, pas seulement des détails sur la mise en œuvre interne.
au lieu de:
écrire:
ou peut-être même:
Je sais, je sais - ce n'est pas un cas pour une assertion statique, mais je veux souligner la valeur informationnelle du message.
Message négatif ou positif?
Cela peut être controversé, mais cela me fait mal de lire des choses comme:
ce sont deux choses contradictoires écrites l'une à côté de l'autre. Donc, chaque fois que j'ai une influence sur la base de code, je pousse pour spécifier ce que nous voulons, en utilisant des verbes supplémentaires comme «must» et «should», et pour ne pas dire ce que nous ne voulons pas.
affirmer a == b, 'a doit être égal à b'
Ensuite, obtenir
AssertionError: a must be equal to b
est également lisible et l'instruction semble logique dans le code. En outre, vous pouvez en tirer quelque chose sans lire le traceback (qui peut parfois même ne pas être disponible).la source
L'utilisation
assert
et la levée d'exceptions concernent la communication.Les assertions sont des déclarations sur l'exactitude du code adressées aux développeurs : une assertion dans le code informe les lecteurs du code des conditions qui doivent être remplies pour que le code soit correct. Une assertion qui échoue au moment de l'exécution informe les développeurs qu'il existe un défaut dans le code qui doit être corrigé.
Les exceptions sont des indications sur des situations non typiques qui peuvent se produire au moment de l'exécution mais ne peuvent pas être résolues par le code à portée de main, adressées au code appelant pour y être traitées. L'occurrence d'une exception n'indique pas qu'il y a un bogue dans le code.
Par conséquent, si vous considérez l'occurrence d'une situation spécifique au moment de l'exécution comme un bug dont vous souhaitez informer les développeurs ("Salut développeur, cette condition indique qu'il y a un bug quelque part, veuillez corriger le code.") Alors allez pour une affirmation. Si l'assertion vérifie les arguments d'entrée de votre code, vous devez généralement ajouter à la documentation que votre code a un "comportement indéfini" lorsque les arguments d'entrée violent ces conditions.
Si à la place, l'occurrence de cette situation n'est pas une indication d'un bug dans vos yeux, mais plutôt une situation (peut-être rare mais) possible qui, selon vous, devrait plutôt être gérée par le code client, déclenchez une exception. Les situations dans lesquelles l'exception est levée doivent faire partie de la documentation du code respectif.
L'évaluation des assertions prend un certain temps. Ils peuvent cependant être éliminés lors de la compilation. Cela a cependant quelques conséquences, voir ci-dessous.
Normalement, les assertions améliorent la maintenabilité du code, car elles améliorent la lisibilité en rendant les hypothèses explicites et en vérifiant régulièrement ces hypothèses lors de l'exécution. Cela aidera également à détecter les régressions. Il y a cependant un problème à garder à l'esprit: les expressions utilisées dans les assertions ne devraient pas avoir d'effets secondaires. Comme mentionné ci-dessus, les assertions peuvent être éliminées au moment de la compilation - ce qui signifie que les effets secondaires potentiels disparaîtraient également. Cela peut - involontairement - changer le comportement du code.
la source
Une assertion consiste à vérifier -
1. la condition valide,
2. l'énoncé valide,
3. la vraie logique;
du code source. Au lieu d'échouer tout le projet, il donne l'alarme que quelque chose n'est pas approprié dans votre fichier source.
Dans l'exemple 1, puisque la variable 'str' n'est pas nulle. Donc, aucune assertion ou exception n'est levée.
Exemple 1:
Dans l'exemple 2, var 'str' est null. Nous évitons donc à l'utilisateur d'aller de l'avant avec un programme défectueux par déclaration assert .
Exemple 2:
Au moment où nous ne voulons pas déboguer et réalisé le problème d'assertion dans le code source. Désactiver l'indicateur d'optimisation
python -O assertStatement.py
rien ne sera imprimé
la source
Dans les IDE tels que PTVS, PyCharm, les
assert isinstance()
instructions Wing peuvent être utilisées pour permettre la complétion de code pour certains objets peu clairs.la source
typing.cast
.Pour ce que ça vaut, si vous traitez avec du code qui repose sur
assert
pour fonctionner correctement, l'ajout du code suivant garantira que les assertions sont activées:la source