Checking the return of the expression "in" changes the result in Python

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 to x < 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 to x < 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

Scroll to Top