[python] Pourquoi "pas (Vrai) dans [Faux, Vrai]" renvoie Faux?


Answers

not x in y est évalué comme x not in y

Vous pouvez voir exactement ce qui se passe en démontant le code. Le premier cas fonctionne comme prévu:

>>> x = lambda: False in [False, True]
>>> dis.dis(x)
  1           0 LOAD_GLOBAL              0 (False)
              3 LOAD_GLOBAL              0 (False)
              6 LOAD_GLOBAL              1 (True)
              9 BUILD_LIST               2
             12 COMPARE_OP               6 (in)
             15 RETURN_VALUE

Le deuxième cas, évalue à True not in [False, True] , qui est False clairement:

>>> x = lambda: not(True) in [False, True]
>>> dis.dis(x)
  1           0 LOAD_GLOBAL              0 (True)
              3 LOAD_GLOBAL              1 (False)
              6 LOAD_GLOBAL              0 (True)
              9 BUILD_LIST               2
             12 COMPARE_OP               7 (not in)
             15 RETURN_VALUE        
>>> 

Ce que vous vouliez exprimer à la place était (not(True)) in [False, True] , ce qui, comme attendu, est True , et vous pouvez voir pourquoi:

>>> x = lambda: (not(True)) in [False, True]
>>> dis.dis(x)
  1           0 LOAD_GLOBAL              0 (True)
              3 UNARY_NOT           
              4 LOAD_GLOBAL              1 (False)
              7 LOAD_GLOBAL              0 (True)
             10 BUILD_LIST               2
             13 COMPARE_OP               6 (in)
             16 RETURN_VALUE        
Question

Si je fais ceci:

>>> False in [False, True]
True

Cela renvoie True . Simplement parce que False est dans la liste.

Mais si je fais:

>>> not(True) in [False, True]
False

Cela renvoie False . Alors que not(True) est égal à False :

>>> not(True)
False

Pourquoi?




Tout tourne autour de la priorité de l'opérateur (c'est plus fort que not ). Mais il peut être facilement corrigé en ajoutant des parenthèses au bon endroit:

(not(True)) in [False, True]  # prints true

l'écriture:

not(True) in [False, True]

est le même comme:

not((True) in [False, True])

qui a l'air si True est dans la liste et renvoie le "non" du résultat.




Pour clarifier certaines autres réponses, l'ajout de parenthèses après un opérateur unaire ne change pas sa priorité. not(True) ne fait not se lier plus étroitement à True . C'est juste un ensemble redondant de parenthèses autour de True . C'est à peu près la même chose que (True) in [True, False] . Les parenthèses ne font rien. Si vous voulez que la liaison soit plus serrée, vous devez placer les parenthèses autour de l'expression entière, ce qui signifie à la fois l'opérateur et l'opérande, c'est-à-dire (not True) in [True, False] .

Pour voir cela d'une autre manière, considérez

>>> -2**2
-4

** se lie plus étroitement que - , ce qui explique pourquoi vous obtenez le négatif de deux carrés, pas le carré des deux négatifs (qui serait positif quatre).

Et si vous vouliez le carré de deux négatifs? Évidemment, vous ajouteriez des parenthèses:

>>> (-2)**2
4

Cependant, il n'est pas raisonnable de s'attendre à ce que les éléments suivants donnent 4

>>> -(2)**2
-4

parce que -(2) est le même que -2 . Les parenthèses ne font absolument rien. not(True) est exactement la même chose.




À côté des autres réponses qui ont mentionné la préséance de not est inférieure in , en fait votre déclaration est équivalente à:

not (True in [False, True])

Mais notez que si vous ne séparez pas votre condition des autres, python utilisera 2 rôles ( precedence ou chaining ) afin de séparer cela, et dans ce cas python a utilisé la précédence. Notez également que si vous souhaitez séparer une condition, vous devez placer toute la condition entre parenthèses, pas seulement l'objet ou la valeur:

(not True) in [False, True]

Mais comme mentionné, il y a une autre modification par python sur les opérateurs qui est en train de chaîner :

Basé sur la 3.x Python:

Notez que les comparaisons, les tests d'appartenance et les tests d'identité ont tous la même priorité et possèdent une fonctionnalité de chaînage de gauche à droite, comme décrit dans la section Comparaisons.

Par exemple, le résultat de l'instruction suivante est False :

>>> True == False in [False, True]
False

Parce que python enchaînera les instructions comme suit:

(True == False) and (False in [False, True])

Qui est exactement False and True qui est False .

Vous pouvez supposer que l'objet central sera partagé entre 2 opérations et d'autres objets (Faux dans ce cas).

Et notez que c'est également vrai pour toutes les comparaisons, y compris les tests d'appartenance et les opérations de tests d'identité qui suivent les opérandes:

in, not in, is, is not, <, <=, >, >=, !=, ==

Exemple :

>>> 1 in [1,2] == True
False

Un autre exemple célèbre est la gamme de numéros:

7<x<20

qui est égal à:

7<x and x<20   



Links