user984003
user984003

Reputation: 29579

python: order of AND execution

If I have the following:

if a(my_var) and b(my_var):
    do something

Can I assume that b() is only evaluated if a() is True? Or might it do b() first?

Asking because evaluating b() will cause an exception when a() is False.

Upvotes: 4

Views: 183

Answers (4)

Martijn Pieters
Martijn Pieters

Reputation: 1123590

b() will only be evaluated if a(my_var) is True, yes. The and operator short-circuits if a(my_var) is falsey.

From the boolean operators documentation:

The expression x and y first evaluates x; if x is false, its value is returned; otherwise, y is evaluated and the resulting value is returned.

You can test this yourself with a function that prints something when called:

>>> def noisy(retval):
...     print "Called, returning {!r}".format(retval)
...     return retval
... 
>>> noisy(True) and noisy('whatever')
Called, returning True
Called, returning 'whatever'
'whatever'
>>> noisy(False) and noisy('whatever')
Called, returning False
False

Python consideres empty containers and numeric 0 values as false:

>>> noisy(0) and noisy('whatever')
Called, returning 0
0
>>> noisy('') and noisy('whatever')
Called, returning ''
''
>>> noisy({}) and noisy('whatever')
Called, returning {}
{}

Custom classes can implement a __nonzero__ hook to return a boolean flag for the same test, or implement a __len__ hook if they are a container type instead; returning 0 means the container is empty and is to be considered false.

On a closely related note, the or operator does the same thing, but in reverse. If the first expression evaluates to true the second expression will not be evaluated:

>>> noisy('Non-empty string is true') or noisy('whatever')
Called, returning 'Non-empty string is true'
'Non-empty string is true'
>>> noisy('') or noisy('But an empty string is false')
Called, returning ''
Called, returning 'But an empty string is false'
'But an empty string is false'

Upvotes: 7

TerryA
TerryA

Reputation: 60004

With the wonderful help of help() (hah):

>>> help('and')

Boolean operations
******************

   or_test  ::= and_test | or_test "or" and_test
   and_test ::= not_test | and_test "and" not_test
   not_test ::= comparison | "not" not_test

...

The expression ``x and y`` first evaluates *x*; if *x* is false, its
value is returned; otherwise, *y* is evaluated and the resulting value
is returned.

...

So yes, if a(my_var) returns False, then the function b will not be called.

Upvotes: 1

Shh
Shh

Reputation: 1006

The compiler always reads top to down and left to right. So If False and True then False is encountered first by the compiler and it exits the if condition. This is valid for all softwares that I know of.

Upvotes: 0

Atmaram Shetye
Atmaram Shetye

Reputation: 1013

Yup, it is safe to do that. Pythons if conditions are lazily evaluated.

Upvotes: 1

Related Questions