Reputation: 122022
So in python, truth conditions can be easily checked and with parenthesis it prioritize the order of true conditions, e.g. these are easy to understand:
>>> 3 > 2
True
>>> (3 > 2) is True
True
But what does these mean, I couldn't grasp the logic of why they return False/True:
>>> 3 > 2 is True
False
>>> 3 > (2 is True)
True
>>> 5 < 3 is False > 2 is True
False
>>> 5 < 3 is False is True > 2 is True
False
>>> 3 < 5 is True is True > 2 is True
False
>>> 3 < 5 is True is True > 2 is True is not False is True
False
>>> 3 < 5 is True is (True > 2 is True is not False) is True
False
>>> 3 < 5 is True is (True > (2 is True) is not False) is True
False
>>> (3 < 5 is True is True) > 2 is (True is not False is True)
False
I know these are not pythonic conditions but how should I understand them? Is it still from left to right?
Or does is True
or/and is False
takes presidence?
Upvotes: 4
Views: 1148
Reputation: 8224
First off, you propably need a little cheat sheet to know the order of evaluation. Most of these operators are on the same bracket and are therefore evaluated left-to-right. With this knowledge, the examples can be translated to their "real" meaning:
(3 < 5 is True is True) > 2 is (True is not False is True)
is equivalent to: (there actually are no __is__
and __not__
, because those are keywords that cannot be overloaded. It's for illustration purposes)
(3.__lt__(5).__is__(True).__is__(True)).__gt__(2).__is__(True.__is__(False).__not__().__is__(True))
I might spared out some details that are described here. The good thing is that you (hopefully) never write such complicated expressions that you need to check the documentation to know what it does.
EDIT: Nevermind, it doesn't work this way with comparisons. Comparisons get compared "all together pairwise", like described in viraptor's answer.
Upvotes: 1
Reputation: 34145
You can analyse each of those cases with dis
module to figure out exactly what's happening. For example:
In [1]: import dis
In [2]: def test():
...: return 3 > 2 is True
...:
In [3]: dis.dis(test)
2 0 LOAD_CONST 1 (3)
3 LOAD_CONST 2 (2)
6 DUP_TOP
7 ROT_THREE
8 COMPARE_OP 4 (>)
11 JUMP_IF_FALSE_OR_POP 21
14 LOAD_GLOBAL 0 (True)
17 COMPARE_OP 8 (is)
20 RETURN_VALUE
>> 21 ROT_TWO
22 POP_TOP
23 RETURN_VALUE
That means the stack looks like this after each step:
0: 3
3: 3 2
6: 3 2 2
7: 2 3 2
8: 2 True
11: 2
14: 2 True
17: False (comparison was: "2 is True")
20: (False is returned)
To me, it looks like a bug in Python to be honest. Maybe there's some good explanation of why this happens, but I'd report it upstream.
Just to rewrite it in equivalent way, the code does:
if 3 > 2:
if 2 is True:
return True
return False
Edit: Maybe it actually makes some weird kind of sense. Consider how checking chained inequalities works:
3 > 2 > 1 == 3 > 2 and 2 > 1
If it generalises to:
x op1 y op2 z == x op1 y and y op2 z
that would explain the result.
Edit2: This actually matches documentation. Have a look at chained comparisons: https://docs.python.org/2/reference/expressions.html#not-in
comparison ::= or_expr ( comp_operator or_expr )*
comp_operator ::= "<" | ">" | "==" | ">=" | "<=" | "<>" | "!="
| "is" ["not"] | ["not"] "in"
is
is considered just as good comparison as >
, so the standard expansion for multiple comparisons is applied.
Other comparisons should be clear now. The only strange new detail needed is: True == 1
, False == 0
, so 3 > False
in 3 > (2 is True)
. Most others can be explained with the expansions. For example:
5 < 3 is False > 2 is True == False
(5 < 3) and (3 is False) and (False > 2) and (2 is True) == False
Upvotes: 3
Reputation: 3568
Boolean
type in python is a subtype of int
. So True
is actually 1 and False
is 0.
All comparison operations in Python have the same priority (>
, <
, >=
, <=
, ==
, !=
, is [not]
, [not] in
).
Comparisons can be chained arbitrarily, e.g.,
x < y <= z
is equivalent tox < y and y <= z
, except that y is evaluated only once (but in both cases z is not evaluated at all whenx < y
is found to be false).Formally, if
a
,b
,c
, ...,y
,z
are expressions andop1
,op2
, ...,opN
are comparison operators, thena op1 b op2 c ... y opN z
is equivalent toa op1 b and b op2 c and ... y opN z
, except that each expression is evaluated at most once.
See Python language reference.
Upvotes: 2