Question:
It is well known that to check if a certain element does not belong to a list, just use the in
operator:
values = [1, 2, 3, 4, 5]
if 9 not in values:
print("9 não pertence à lista.")
else:
print("9 pertence à lista.")
# 9 não pertence à lista.
See working on Ideone | Repl.it
And that this operator returns True
when the element belongs to the list in question or False
otherwise, and this return can be assigned to a variable:
condition = 9 in values
print(condition) # False
See working on Ideone | Repl.it
In this case, you can use the variable as the condition:
if condition == False:
print("9 não pertence à lista.")
else:
print("9 pertence à lista.")
# 9 não pertence à lista.
However, if you use the expression with direct in
this check, the result is changed:
if 9 in values == False:
print("9 não pertence à lista.")
else:
print("9 pertence à lista.")
# 9 pertence à lista.
See working on Ideone | Repl.it
In this last syntax, the result is that 9 belongs to the list (even if it doesn't).
Why is this happening? Is this behavior expected from Python? If so, how does he analyze this last expression?
Answer:
What happens there is a little confusion, perhaps because of the custom with other languages and because of the less "obvious" form of this expression.
A little about comparisons
In Python, unlike most languages I know, it's possible to have expressions of the form a < b < c
. This is very common in mathematics and the interpretation of this expression in Python is the same way.
For example:
a = 2
b = 3
c = 4
print(a < b < c)
# True
See working on Repl.it
The above expression will evaluate a < b and b < c
.
A little piece of documentation that talks about it :
(…) Also unlike C, expressions like
a < b < c
have the interpretation that is conventional in mathematics (…)(…) Comparisons can be chained arbitrarily, eg,
x < y <= z
is equivalent tox < y and y <= z
(…)
In free translation:
(…) Also unlike C, expressions like
a < b < c
have the interpretation that is conventional in mathematics (…)(…) Comparisons can be arbitrarily chained together, for example:
x < y <= z
is equivalent tox < y and y <= z
what happens in your code
The first thing that comes to mind when looking at the expression 9 in values == False
is that the interpreter should evaluate the result of 9 in values
and after that, compare it with False
.
In fact, the expression ends up falling in the case above and evaluates to 9 in values and values == False
.
Which, in turn, evaluates to False and True
and after that to False
For example:
a = 'ana'
b = 'nana'
c = 'banana'
print(a in b in c)
# True
See working on Repl.it