Vous vous heurtez au chaînage des opérateurs de comparaison ; 1 in () == False
fait pas moyenne (1 in ()) == False
.
Au contraire, les comparaisons sont enchaînées et l'expression signifie réellement :
(1 in ()) and (() == False)
Parce que (1 in ())
est déjà fausse, la seconde moitié de l'expression chaînée est ignorée (car False and something_else
renvoie à False
quelle que soit la valeur de something_else
serait).
Voir le documentation sur les comparaisons et les expressions :
Les comparaisons peuvent être enchaînées arbitrairement, par exemple, x < y <= z
est équivalent à x < y and y <= z
sauf que y
n'est évalué qu'une seule fois (mais dans les deux cas z
n'est pas évalué du tout lorsque x < y
s'avère être fausse).
Pour mémoire, <
, >
, ==
, >=
, <=
, !=
, is
, is not
, in
y not in
sont tous des opérateurs de comparaison (tout comme le déprécié <>
).
En général, ne comparez pas les booléens ; testez simplement l'expression elle-même. Si vous ont pour effectuer un test par rapport à un littéral booléen, utilisez au moins les parenthèses et la balise is
opérateur, True
y False
sont des singletons, tout comme None
:
>>> (1 in ()) is False
True
Cela devient encore plus confus lorsque des nombres entiers sont impliqués. La méthode Python bool
est une sous-classe de int
1 . En tant que tel, False == 0
est vrai, tout comme True == 1
. Il est donc possible de créer des opérations enchaînées qui ont l'air presque normales :
3 > 1 == True
est vrai parce que 3 > 1
y 1 == True
sont toutes deux vraies. Mais l'expression :
3 > 2 == True
est fausse, car 2 == True
est fausse.
1 <code>bool</code> est une sous-classe de <code>int</code> pour des raisons historiques ; Python n'a pas toujours eu un <code>bool</code> et des entiers surchargés avec une signification booléenne, comme le fait le C. Création de <code>bool</code> une sous-classe a permis à l'ancien code de fonctionner.