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?
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.
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
_
Priorité des opérateurs. in
se lie plus étroitement que not
, votre expression est donc équivalente à not((True) in [False, True])
.
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.
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.
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
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.
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).
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