Pourquoi (1 in [1,0] == True) est-il évalué à False?

153

Lorsque j'ai cherché des réponses à cette question , j'ai constaté que je ne comprenais pas ma propre réponse.

Je ne comprends pas vraiment comment cela est analysé. Pourquoi le deuxième exemple renvoie-t-il False?

>>> 1 in [1,0]             # This is expected
True
>>> 1 in [1,0] == True     # This is strange
False
>>> (1 in [1,0]) == True   # This is what I wanted it to be
True
>>> 1 in ([1,0] == True)   # But it's not just a precedence issue!
                           # It did not raise an exception on the second example.

Traceback (most recent call last):
  File "<pyshell#4>", line 1, in <module>
    1 in ([1,0] == True)
TypeError: argument of type 'bool' is not iterable

Merci pour toute aide. Je pense que je dois rater quelque chose de vraiment évident.


Je pense que c'est subtilement différent du duplicata lié:

Pourquoi l'expression 0 <0 == 0 renvoie False en Python? .

Les deux questions concernent la compréhension humaine de l'expression. Il semblait y avoir deux façons (à mon avis) d'évaluer l'expression. Bien sûr, ni l'un ni l'autre n'étaient corrects, mais dans mon exemple, la dernière interprétation est impossible.

En 0 < 0 == 0vous regardant, vous pourriez imaginer que chaque moitié est évaluée et a un sens en tant qu'expression:

>>> (0 < 0) == 0
True
>>> 0 < (0 == 0)
True

Ainsi, le lien répond pourquoi cela évalue False:

>>> 0 < 0 == 0
False

Mais avec mon exemple 1 in ([1,0] == True)n'a pas de sens en tant qu'expression, donc au lieu qu'il y ait deux interprétations possibles (certes erronées), une seule semble possible:

>>> (1 in [1,0]) == True
Peter Wood
la source
1
Priorité des opérateurs ... la ==liaison est plus étroite que in, donc [1,0] == Trueest évaluée en premier, puis le résultat de cela est alimenté 1 in other_result.
Marc B
J'ai supprimé la balise Python-2.7, car Python 3.2 se comporte de la même manière.
lvc
1
@Marc B: n'explique pas la deuxième expression
Scott Hunter
32
@MarcB, la question comprenait un test utilisant des parenthèses pour réfuter cette interprétation.
Mark Ransom

Réponses:

194

Python applique ici le chaînage d'opérateurs de comparaison. L'expression est traduite en

(1 in [1, 0]) and ([1, 0] == True)

ce qui est évidemment False.

Cela se produit également pour des expressions telles que

a < b < c

qui se traduisent par

(a < b) and (b < c)

(sans évaluer bdeux fois).

Consultez la documentation du langage Python pour plus de détails.

Sven Marnach
la source
40
Une preuve supplémentaire pour cela, 1 in [1, 0] == [1, 0]évalue à True.
Andrew Clark
9
J'ai longtemps pensé à cela comme à une verrue linguistique. J'aurais préféré que l' inopérateur ait une priorité plus élevée que les autres opérateurs de comparaison et qu'il n'enchaîne pas. Mais il me manque peut-être un cas d'utilisation.
Steven Rumbalski
3
belle prise, je n'y ai même pas pensé. Cela n'a pas beaucoup de sens d'autoriser le chaînage de in- après tout a du x < y < zsens, mais pas tellement avecx in y in z
BlueRaja - Danny Pflughoeft
7
@Sven Utile: peut-être. Lisible: certainement pas. Python prétend émuler une typographie mathématique commune avec cette convention, mais lorsqu'il est utilisé avec incela, ce n'est tout simplement plus le cas et le rend assez contre-intuitif.
Konrad Rudolph
6
@KonradRudolph: J'ai vu plus d'une fois des pensées comme "1 ≤ x ∈ ℝ" dans les textes mathématiques, mais je suis fondamentalement d'accord avec vous.
Sven Marnach