Boolean comparison in python [duplicate] - python

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.

Related

What kind of logic does Python uses to handle Boolean expressions?

So I just started learning Python, and while I was just playing with the shell I came around a weird thing.
print(5!=6==True,"=",True) #Gave False=True
print(5!=6==False,"=",True) #Gave False=True
print(5!=6!=True,"=",True) #Gave True=True
Can anyone explain to me why does this happen
the expression a op1 b op2 c is equivalent to (a op1 b) and (b op2 c)
https://docs.python.org/3/reference/expressions.html#comparisons
https://www.geeksforgeeks.org/chaining-comparison-operators-python/
mainly used to enable easy declaration of constraints such as min < x < max
What's interesting about this is it isn't about regular operator precedence. Adding parentheses doesn't give the same result:
>>> 5!=6==True
False
>>> (5!=6)==True
True
>>> 5!=(6==True)
True
The first one is actually parsed as a chained comparison:
5!=6 and 6==True
which is True and False (result False).
The more natural use of chained comparisons is:
x = 5
if 0 < x < 10: # True
which is parsed as:
0 < x and x < 10

Confusion related to Python's `in` operator [duplicate]

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).

Why this statement is evaluated to False even it is true? [duplicate]

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

Python order of operations involving "in" and "==" [duplicate]

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).

Multiple comparison operators in single statement (chaining comparison operators)

Does this do what I think it does?
assert 1 < 2 < 3
I couldn't find any reference to this in the docs but I saw it in a high rep answer.
It seems to work but it could be luck, like the leftmost resolves to True, then True is used in the other.
I did a few tests and it always work as expected, but I'd like to find a source (a doc) stating explicitly that it is intended.
>>> 1<2<3<4<5
True
>>> 1<2<7<4<5
False
>>> 1<2<3>2<5
True
This rules out the "leftmost first" hypothesis:
>>> 1<3<2
False
>>> (1<3)<2
True
This is documented in detail in the Expressions chapter of the documentation:
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.
Note that a op1 b op2 c doesn’t imply any kind of comparison between a
and c, so that, e.g., x < y > z is perfectly legal (though perhaps not
pretty).

Categories

Resources