web-dev-qa-db-fra.com

Pourquoi "not (True) in [False, True]" ne renvoie-t-il False?

Si je fais ça:

>>> False in [False, True]
True

Cela retourne True. Tout simplement parce que False est dans la liste.

Mais si je le fais:

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

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

>>> not(True)
False

Pourquoi?

473
Texom512

Priorité de l'opérateur  2.x , .x. La priorité de not est inférieure à celle de in. Donc, cela équivaut à:

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

Voici ce que tu veux:

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

Comme @Ben le fait remarquer: il est recommandé de ne jamais écrire not(True), préférez not True. La première le fait ressembler à un appel de fonction, tandis que not est un opérateur, pas une fonction.

724
Yu Hao

not x in y est évalué en tant que x not in y

Vous pouvez voir exactement ce qui se passe en désassemblant 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, évalué à _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]_, qui comme prévu 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        
_
74
Roshan Mathews

Priorité des opérateurs. in se lie plus étroitement que not, votre expression est donc équivalente à not((True) in [False, True]).

35
mooiamaduck

Tout dépend de priorité de l'opérateur (in est plus fort que not). Mais cela 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 regarde si True est dans la liste et retourne le "pas" du résultat.

33
alfasin

Il s’évalue comme not True in [False, True], qui renvoie False car True est dans [False, True].

Si tu essayes

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

Vous obtenez le résultat attendu.

14
user3636636

Outre les autres réponses mentionnant que la précédence de not est inférieure à in, votre déclaration équivaut en réalité à:

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 utilisé la priorité. Notez également que si vous souhaitez séparer une condition, vous devez la mettre entre parenthèses et pas seulement l'objet ou la valeur:

(not True) in [False, True]

Mais comme mentionné, il y a une autre modification apportée par python sur les opérateurs: chaining:

Basé sur python documentation :

Notez que les comparaisons, les tests d'appartenance et les tests d'identité ont tous la même priorité et ont une fonction chaînagede 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 (False dans ce cas).

Et notez que cela est également vrai pour toutes les comparaisons, y compris les tests d'appartenance et les opérations de test 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 plage de numéros:

7<x<20

qui est égal à:

7<x and x<20   
13
Kasrâmvd

Pour clarifier certaines des autres réponses, l’ajout de parenthèses after un opérateur unaire ne change pas sa priorité. not(True) ne rend pas not plus étroitement lié à True. C'est juste un ensemble redondant de parenthèses autour de True. C'est un peu la même chose que (True) in [True, False]. Les parenthèses ne font rien. Si vous voulez que la liaison soit plus étroite, vous devez mettre les parenthèses autour de l'expression entière, signifiant à la fois l'opérateur et l'opérande, c'est-à-dire (not True) in [True, False].

Pour voir cela autrement, considérons

>>> -2**2
-4

** se lie plus étroitement que -, raison pour laquelle vous obtenez le négatif de deux carrés, pas le carré de deux négatifs (qui serait quatre positifs).

Et si vous vouliez le carré du négatif deux? É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 identique à -2. Les parenthèses ne font absolument rien. not(True) est exactement la même chose.

6
asmeurer

Voyons cela comme une opération de vérification du confinement de la collection: [False, True] est une liste contenant des éléments.

L'expression True in [False, True] renvoie True, car True est un élément contenu dans la liste.

Par conséquent, not True in [False, True] donne le "booléen opposé", not résultat de l'expression ci-dessus (sans parenthèses pour préserver la priorité, car in a une priorité supérieure à not opérateur). Par conséquent, not True donnera False.

D'autre part, (not True) in [False, True], est égal à False in [False, True], qui est True (False figure dans la liste).

6
Nick Louloudakis

Ici est la documentation sur la priorité des opérateurs

in binds tighter than not

Ainsi, cela servira le but

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