This question already has answers here:
Unexpected result from `in` operator - Python [duplicate]
(3 answers)
Closed 2 years ago.
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
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).
Related
This question already has answers here:
python operator precedence of in and comparison [duplicate]
(3 answers)
Closed 3 years ago.
Can someone explain to me why the Python interpreter evaluates this expression to be False?
1 in [1] == True
I would expect that 1 in [1] would evaluate to True, and obviously True == True would be True. However this isn't what happens - the expression is False. Why does this happen?
== and in are both comparison operators. And when you have multiple comparison operators like this, Python considers it a chained comparison. For example, 1 < x < 10 is equivalent to 1 < x and x < 10.
In your case, 1 in [1] == True is equivalent to (1 in [1]) and ([1] == True), which evaluates to False.
If you have an expression like this python split it to more statements. In fact:
1 in [1] == True equals to: (1 in [1]) and ([1] == True)
Right side is false since [1] != True and whole sentence is false
This question already has answers here:
python operator precedence of in and comparison [duplicate]
(3 answers)
Closed 3 years ago.
I started learning python but I've noticed something unsual, something that I do not understand, why the expression provided below it's evaluated to false even it is true??
l = [1,2,3,4,5,"Hi"]
"Hi" in l # returns True
"Hi" in l == True # returns False
"Hi" in l == True is evaluated as ("Hi" in l) and (l == True) which is False.
Explanation from documentation:
Comparisons can be chained arbitrarily, e.g., x < y <= z is equivalent
to x < y and y <= z
This question already has an answer here:
Why does (1 in [1,0] == True) evaluate to False?
(1 answer)
Closed 4 years ago.
I noticed the following strange behavior:
'a' in 'a' == True # Returns False
('a' in 'a') == True # Returns True
'a' in ('a' == True) # throws TypeError
How is the first expression parsed? Both placements of parentheses yield different results.
(Python 3.6)
From the docs:
Note that comparisons, membership tests, and identity tests, all have the same precedence and have a left-to-right chaining feature as described in the Comparisons section.
in and == are membership and comparison operators respectively.
From Comparisons:
... expressions like a < b < c have the interpretation that is conventional in mathematics:
[...]
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).
This question already has answers here:
Check if a word exists in a dictionary doesn't find any word
(1 answer)
Is `a<b<c` valid python?
(2 answers)
Closed 5 years ago.
Python seems to evaluate oddly with (what I thought) would be relatively straightforward syntax. Can anyone shed light on what's happening behind the scenes here? What does python think is happening in the first case?
>>> x = 'foo'
>>> 'f' in x == True
False
>>> ('f' in x) == True
True
>>> 'f' in (x == True)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: argument of type 'bool' is not iterable
What you see here is chained comparisons:
'f' in x == True
Both in and == are both comparisons. Now Python interprets chained comparison interpreters with an implicit and. So you have basically written:
'f' in x and x == True
and the second check fails.
The same occurs if you for instance write:
a < b in c
it is short for:
a < b and b in c
(except that expressions are only evaluated once).
If we take a look at the documentation, we see that there are 11 comparators:
comp_operator ::= "<" | ">" | "==" | ">=" | "<=" | "<>" | "!="
| "is" ["not"] | ["not"] "in"
and furthermore it states:
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).
Formally, if a, b, c, ..., y, z are expressions and op1,
op2, ..., opN are comparison operators, then a op1 b op2 c ... y
opN z is equivalent to a op1 b and b op2 c and ... y opN z, except
that each expression is evaluated at most once.
Can someone explain how these results are possible (python 2.6):
>>> 1<3>2
True
>>> (1<3)>2
False
>>> 1<(3>2)
False
I would think that one of the last two would match the first one, but apparently the operators in the first statement is somehow linked?!
Your first example shows comparison chaining. 1<3>2 means 1<3 and 3>2 (except each expression is evaluated only once). This applies to all comparison operators in Python.
Your second two examples force one comparison to be evaluated first, resulting in a boolean value which is then compared with the remaining integer.
In your first case 1<3>2 1 is actually lesser than 3 and 3 is greater than 2, so True.
In your second case (1<3)>2 (1<3) evaluates as True that represented as 1, so 1 is not greater than 2.
In your third case 1<(3>2), 1 is not lesser than True that represented as 1.
The last two statements compare booleans against an integer:
>>> True > 2
False
>>> 1 < True
False
The first statement is comparison chaining, which works for all boolean comparisons in Python. Note from the documentation:
Comparisons yield boolean values: True or False.
By placing parts of your expression in brackets, those parts get evaluated first and you end up with comparing integers and booleans.
As per docs,
Unlike C, all comparison operations in Python have the same priority, which is lower than that of any arithmetic, shifting or bitwise operation. Also unlike C, expressions like a < b < c have the interpretation that is conventional in mathematics:
comparison ::= or_expr ( comp_operator or_expr )*
comp_operator ::= "<" | ">" | "==" | ">=" | "<=" | "<>" | "!="
| "is" ["not"] | ["not"] "in"
Comparisons yield boolean values: True or False.
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).