I was playing around with logical expressions in the python interpreter, and I can't seem to figure out what execution procedure python is really using under the hood. I've seen this table (http://www.mathcs.emory.edu/~valerie/courses/fall10/155/resources/op_precedence.html) as describing the operator precedence that python uses.
1)
print("this") or True and 1/0 and print("tester")
when I type that into the python interpreter I get the output of "this" and then zero division error. However, the site I referenced mention that function calls are the second highest precedence, so shouldn't both function calls of print be executed first? I know there's short circuit evaluation, but doesn't that kick in only once you get to the precedence level of the ands, nots, and ors?
2)
True>False or print("hello")
even this outputs only True on the python interpreter. why doesn't it do the function call of print first?
3)
5 is 5 or 1/0
This outputs True. But shouldn't division have higher precedence than "is" and shouldn't this expression return a ZeroDivsionError?
Can someone explain what I'm missing and how to tell in what order python will execute a logical expression?
Can someone explain what I'm missing and how to tell in what order python will execute a logical expression?
Precedence affects which way "shared" operands will be grouped when parsing to a tree. Past that, the specific evaluation model of each sub-expression takes over.
print("this") or True and 1/0 and print("tester")
You get a tree which looks like this (you can get the more verbose but exact version using the ast
module, and astpretty
to get something readable):
or
print("this")
and
True
and
1/0
print("tester")
Then evaluation takes over (after a compilation to bytecode but that doesn't change the order of operation):
or
is evaluated
print
, which returns a falsy value, thereforeand
True
which is truthyand
1/0
which blows upTrue>False or print("hello")
This parses to
or
>
True
False
print("hello")
or
evaluates its first operand
(> True False)
evaluates to True
or
is a short-circuiting operator, it stops as soon as it finds a truthy value and returns that, so it never gets to the print
5 is 5 or 1/0
This parses to
or
is
5
5
/
1
0
or
is evaluated
is
is evaluated, and returns True
as above, or
is a short-circuiting operator and returns the first truthy value, so it returns immediately.
I left out some bits e.g. technically /
evaluates both operands then applies its operation, function calls evaluate all their parameters then perform the call itself.
and
and or
stand out because they perform logic after the evaluation of each operand, not after having evaluated all of them (they're lazy / short-circuiting): and
returns the first falsy result it gets, or returns the first truthy result it gets, potentially evaluating only the first of their operands.