web-dev-qa-db-fra.com

python assert avec et sans parenthèses

Voici quatre invocations simples d'assert:

>>> assert 1==2
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
AssertionError

>>> assert 1==2, "hi"
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
AssertionError: hi

>>> assert(1==2)
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
AssertionError

>>> assert(1==2, "hi")

Notez que le dernier ne génère pas d'erreur. Quelle est la différence entre appeler assert avec ou sans parenthèse qui provoque ce comportement? Ma pratique consiste à utiliser des parenthèses, mais ce qui précède suggère que je ne devrais pas.

85
gaefan

Le dernier assert vous aurait donné un avertissement (SyntaxWarning: assertion is always true, perhaps remove parentheses?) Si vous l'aviez exécuté via un interpréteur complet, pas via IDLE. Étant donné que assert est un mot clé et non une fonction, vous passez en fait un Tuple comme premier argument et vous laissez le deuxième argument.

Rappelez-vous que les tuples non vides sont évalués à True, et puisque le message d'assertion est facultatif, vous avez essentiellement appelé assert True Lorsque vous avez écrit assert(1==2, "hi").

104
Mark Rushakoff

Si vous mettez la parenthèse là-dedans parce que vous vouliez une assertion sur plusieurs lignes, alors une alternative est de mettre une barre oblique inverse à la fin de la ligne comme ceci:

foo = 7
assert foo == 8, \
    "derp should be 8, it is " + str(foo)

Tirages:

AssertionError: "derp should be 8, it is 7

Pourquoi cela python assert doit être différent de tout le reste:

Je pense que l'idéologie pythonique est qu'un programme devrait s'auto-corriger sans avoir à se soucier du drapeau spécial pour activer les assertions. La tentation de désactiver les assertions est trop grande et est donc obsolète.

Je partage votre agacement que le python assert a une syntaxe unique par rapport à toutes les autres constructions de programmation python, et cette syntaxe a encore changé depuis python2 à python3 et à nouveau changé de python 3.4 à 3.6. Rendre les déclarations d'assertion non rétrocompatibles de toute version à toute autre version.

C'est un coup sur l'épaule que assert est un citoyen de 3ème classe, il sera totalement supprimé en python4, et certainement encore en Python 8.1.

20
Eric Leschinski

assert 1==2, "hi" Est analysé comme assert 1==2, "hi" Avec "hi" comme deuxième paramètre du mot-clé. D'où la raison pour laquelle il donne correctement une erreur.

assert(1==2) est analysé en tant que assert (1==2) qui est identique à assert 1==2, car les parens autour d'un seul élément ne créent pas de Tuple sauf s'il y a une virgule de fin, par exemple (1==2,).

assert(1==2, "hi") est analysé comme assert (1==2, "hi"), ce qui ne donne pas d'erreur car un Tuple non vide (False, "hi") n'est pas une fausse valeur et il n'y a pas de second paramètre fourni au mot-clé.

Vous ne devez pas utiliser de parenthèses car assert n'est pas une fonction dans Python - c'est un mot-clé.

15
Amber

Vous pouvez rompre l'instruction assert sans \ comme ça:

foo = 7
assert foo == 8, (
    'derp should be 8, it is ' + str(foo))

Ou si vous avez un message encore plus long:

foo = 7
assert foo == 8, (
    'Lorem Ipsum is simply dummy text of the printing and typesetting '
    'industry. Lorem Ipsum has been the industry\'s standard dummy text '
    'ever since the 1500s'
)
8
karantan

Ce qui suit est cité dans le doc python

Les instructions d'assertion sont un moyen pratique d'insérer des assertions de débogage dans un programme:

assert_stmt ::= "assert" expression ["," expression]

La forme simple, expression d'assertion, équivaut à if __debug__: if not expression: raise AssertionError

La forme étendue, assert expression1, expression2 , est équivalente à if __debug__: if not expression1: raise AssertionError(expression2)

Donc, lorsque vous utilisez des parenthèses ici, vous utilisez le formulaire simple, et l'expression est évaluée comme un tuple, qui est toujours True lors de la conversion en bool

1
VicX