I have a line of code in my script that has both these operators chained together. From the documentation reference BOOLEAN AND has a lower precedence than COMPARISON GREATER THAN. I am getting unexpected results here in this code:
>>> def test(msg, value):
... print(msg)
... return value
>>> test("First", 10) and test("Second", 15) > test("Third", 5)
First
Second
Third
True
I was expecting Second or Third test to happen before the fist one, since >
operator has a higher precedence. What am I doing wrong here?
https://docs.python.org/3/reference/expressions.html#operator-precedence
Python follows the same precedence rules for its mathematical operators that mathematics does. Parentheses have the highest precedence and can be used to force an expression to evaluate in the order you want. Since expressions in parentheses are evaluated first, 2 * (3-1) is 4, and (1+1)**(5-2) is 8.
In the first expression, the bitwise-AND operator ( & ) has higher precedence than the logical-OR operator ( || ), so a & b forms the first operand of the logical-OR operation.
Because you are looking at the wrong thing. call
(or function call) takes higher precendence over both and
as well as >
(greater than) . So first function calls occur from left to right.
Python will get the results for all function calls before either comparison happens. The only thing that takes precendence over here would be short circuiting , so if test("First",10)
returned False, it would short circuit and return False.
The comparisons and and
still occur in the same precendence , that is first the result of test("Second", 15)
is compared against test("Third", 5)
(please note only the return values (the function call already occured before)) . Then the result of test("Second", 15) > test("Third", 5)
is used in the and
operation.
From the documentation on operator precedence -
One way to see what's happening is to look at exactly how Python is interpreting this result:
>>> x = lambda: test("First", 10) and test("Second", 15) > test("Third", 5)
>>> dis.dis(x)
1 0 LOAD_GLOBAL 0 (test)
3 LOAD_CONST 1 ('First')
6 LOAD_CONST 2 (10)
9 CALL_FUNCTION 2
12 JUMP_IF_FALSE_OR_POP 42
15 LOAD_GLOBAL 0 (test)
18 LOAD_CONST 3 ('Second')
21 LOAD_CONST 4 (15)
24 CALL_FUNCTION 2
27 LOAD_GLOBAL 0 (test)
30 LOAD_CONST 5 ('Third')
33 LOAD_CONST 6 (5)
36 CALL_FUNCTION 2
39 COMPARE_OP 4 (>)
>> 42 RETURN_VALUE
If you do the same for 10 and 15 > 5
, you get:
>>> x = lambda: 10 and 15 > 5
>>> dis.dis(x)
1 0 LOAD_CONST 1 (10)
3 JUMP_IF_FALSE_OR_POP 15
6 LOAD_CONST 2 (15)
9 LOAD_CONST 3 (5)
12 COMPARE_OP 4 (>)
>> 15 RETURN_VALUE
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With