13

I found strange behavior with Python's in operator

d = {}
'k' in d == False # False! 

I thought it's because of precedence:

('k' in d) == False # True, it's okay
'k' in (d == False) # Error, it's also okay

But, what precedence evaluates the following expression then?

d = {}
'k' in d == False

If it's because of wrong precedence why it doesn't fire an error like if:

'k' in (d == False)

In other words, what happens under the hood of Python with this expression?

'k' in d == False
Nikita
  • 194
  • 10
  • 1
    `'k' in [d == False]` will evaluate to `False` – bigbounty Jul 31 '20 at 12:32
  • 1
    I'll remember to ask this again some day. Astounding that this still collects so many upvotes, unlike other unresearched duplicate questions which just gather downvotes. – superb rain Jul 31 '20 at 13:43

1 Answers1

23

in is considered a comparison operator, and so it is subject to comparison chaining.

'k' in d == False

is equivalent to

'k' in d and d == False

because both in and == are comparison operators.

You virtually never need direct comparison to Boolean literals, though. The "correct" expression here is 'k' not in d.


For reference, this is described in the Python documentation, under 6.10. Comparisons:

comparison    ::=  or_expr (comp_operator or_expr)*
comp_operator ::=  "<" | ">" | "==" | ">=" | "<=" | "!="
                   | "is" ["not"] | ["not"] "in"

and

Comparisons can be chained arbitrarily, e.g., x < y <= z is equivalent to x < y and y <= z, except that y is evaluated only once (but in both cases z is not evaluated at all when x < y is found to be false).

chepner
  • 497,756
  • 71
  • 530
  • 681