Skip to main content

Foundations of Python Programming: Functions First

Section 5.11 Short-Circuit Evaluation

Subsection 5.11.1 Smart Evaluation

Python is “smart” about the way it evaluates expressions using boolean operators. Consider the following example:
answer = input('Continue?')
if answer == 'Y' or answer == 'y':
   print('Continuing!')
There are two operands for the or operator here: answer == 'Y' and 'answer == 'y'. Python evaluates from left to right, and if the first operand for or evaluates to True, Python doesn’t bother evaluating the second operand, because it knows the result must be True (recall that if either operand for or is True, the result is True). So, if the user enters Y, Python first evaluates answer == 'Y', determines that it is True, and doesn’t bother to check to see if answer == 'y' is True; it just concludes that the entire condition is True and executes the print statement.
In a similar fashion, with the and operator, if the first operand evaluates to False, Python doesn’t check the second operand’s value, because it can conclude that the result must be False.
This behavior, in which Python in some cases skips the evaluation of the second operand to and and or, is called short-circuit boolean evaluation. You don’t have to do anything to make Python do this; it’s the way Python works. It saves a little processing time. And, as a special bonus, you can take advantage of Python’s short-circuiting behavior to shorten your code. Consider the following example:
This code checks to see if the average weight of a given number of pieces of luggage is greater than 50 pounds. However, there is a potential crash situation here. If the user enters 0 for num_pieces, the program will crash with a divide by zero error. Try it out to see it happen.
To prevent the crash, you might add an extra if statement to check for zero:
if num_pieces != 0:
   if total_weight / num_pieces > 50:
      print('Average weight is greater than 50 pounds -> $100 surcharge.')
Now, the division will not occur if num_pieces is zero, and a potential runtime crash has been averted. Good job!
We can use short-circuit evaluation to shorten this example to a single if statement. Anytime you have two nested if statements as in the example above, you can combine them into a single if statement by joining the conditions using the and operator. Consider the version below, and think about why this if statement is equivalent in its behavior to the previous version with two nested if statements:
But wait a minute: is this code safe? Try running the program and entering the value 500 for total_weight and the value 5 for num_pieces. Then, try it again using the value 0 for num_pieces. There should be no crash.
Next, try altering the code and reversing the order of the if conditions:
if total_weight / num_pieces > 50 and num_pieces != 0:
   print('Average weight is greater than 50 pounds -> $100 surcharge.')
Run the program again, performing the same two tests. This time, you should observe a crash when you enter 0 for num_pieces. Can you analyze why the first version did not crash, but the second one does?
In the second version, when evaluating left-to-right, the division by zero occurs before Python evaluates the comparison num_pieces != 0. When joining two if statements into a single if statement, you must be sure to put the condition from the first if statement on the left-hand side of the and operator, and the other condition on the right-hand side, in order to get the same effect.
To summarize this discussion on smart evaluation, keep in mind that when you are performing potentially dangerous operations in an if statement using boolean logic with and or or, order matters!
You have attempted of activities on this page.