We’ll address the meaning of conditional processing in Conditional Processing. We’ll present the basic Python if statement in The if Statement. We’ll look at some examples in Example if Statements.
We’ll add a number of conditional processing features in The elif Condition for Alternatives, The else Condition as a Catch-All and The pass Statement: a Do-Nothing.
The programs we’ve seen so far have performed a sequence of steps, unconditionally. We’re going to introduce some real sophistication by making some of those steps conditional. We’ll start by looking at what it takes to design a sequence of steps that does what we want.
Back in Where Exactly Did We Expect To Be? we talked about the significance of putting a variable name on an object. The values we assign to our variables define the program’s state of being. Changing a variable’s value changes the program’s state. When we’ve planned our program well, each state change moves our program from a nebulous starting state toward the well-defined finished state.
Let’s look at converting Celsius temperatures to Fahrenheit temperatures. We’ll work backwards from the ending.
When we reverse this list of goals, we have the algorithm for computing the Fahrenheit temperature from the Celsius temperature.
This example shows sequential execution, where each step is unconditional. Sometimes the processing in a given step depends on a condition being met. When we are planning our programs, we may have to choose one of several statements depending on the data values or the processing goal. We call this conditional processing, which is the subject of this chapter.
The next state may depend on a condition being true for all of a set of data or finding a condition true for some of a set of data. We call this iterative processing, and that’s the subject of the While We Have More To Do : The for Statement chapter.
Many times a program’s exact processing or state change depends on a condition. Conditional processing is done by setting statements apart in groups called suites that have conditions attached to the suites. The Python syntax for this is an if statement. The if embodies this semantics of “if a condition is true, execute the suite of statements” .
The basic syntax of an if statement looks like this:
if expression :
suite
The word if and the : are essential syntax. The suite is an indented block of one or more statements. Any statement is allowed in the block, including indented if statements. You can use either tabs or spaces for indentation. The usual style is four spaces, and we often set BBEdit or TextPad to treat the tab key on our keyboard as four spaces.
This is the first compound statement we’ve seen. A compound statement statement makes use of the essential syntax rules we looked at in Long-Winded Statements. It also uses two additional syntax rules, that we’ll look at next.
Semantics. The if statement evaluates the condition expression first. When the result is True, the suite of statements is executed. Otherwise the suite is skipped. Let’s look at some examples.
We’ll look at some examples of if statements to see some additional examples of how they work. We’ll take a couple of examples from the rules for Craps.
Is This Craps?. During the game of Craps, once a point is established, a roll of 7 is “craps”, a loser. The following example combines arithmetic expressions, comparison and the if statement.
The variables d1 and d2 are set randomly, so each time you run this it may behave differently.
d1, d2= random.randint(1,6), random.randint(1,6)
if d1+d2 == 7:
print("craps")
Here’s how this if statement works.
The expression d1+d2 == 7 is evaluated.
The expression d1+d2 is evaluated to get an integer sum.
The 7 doesn’t need to be evaluated.
The comparison is performed to see if the d1+d2 sum really is equal to 7. The result is either True or False.
If the expression’s value is True, the suite is executed. This will print the message.
If the value is False, the suite is silently skipped.
Come Out Roll. Here’s a second example from the game of Craps. On the first roll, the come out roll, if two dice show a total of 7 or 11, the throw is a winner.
d1, d2= random.randint(1,6), random.randint(1,6)
if d1+d2 == 7 or d1+d2 == 11:
print("winner", d1+d2)
Here we have a typically complex expression. Here’s how the if statement works.
The expression d1+d2 == 7 or d1+d2 == 11 is evaluated.
The or operator evaluates the left side of the or operation first; if this is False, it will then evaluate the right side. If the left side is True, the result is True.
The expression d1+d2 == 7 is evaluated.
If this value is True, ( d1 + d2 really is 7), the entire or expression is True and evaluation of the expression is complete.
If the left side is False, then the right side is evaluated. The value of the right side (d1+d2 == 11) is the value for the entire or operation. This could be True or False.
If the value of the expression is True, the suite is executed, which means that a message is printed.
If the expression is True, the suite is skipped.
Syntax Help from IDLE. The suite of statements inside the if statement is set apart from other statements by its indentation. This means you have to indent the statements in the suite consistently. Any change to the indentation is, in effect, another suite or the end of this suite.
The good news is the IDLE knows this rule and helps us by automatically indenting when we end a line with a :. It will automatically indent until we enter a blank line. Here’s how it looks in IDLE. In order to show you precisely what’s going on, we’re going to replace normally invisible spaces with _ characters.
>>>_if_1+2_==_3: ...____print(“good”) ... good
Important
Syntax Rule Eight
Compound statements, including if, while, for, have an indented suite of statements. You have a number of choices for indentation; you can use tab characters or spaces. While there is a lot of flexibility, the most important thing is to be consistent.
We’ll show an example with spaces shown via _.
a=0 if_a==0: ____print(“a_is_zero”) else: ____print(“a_is_not_zero”)
Here’s an example with spaces shown via _ and tabs shown with ⊢:
if_a%2==0: ⊢print(“a_is_even”) else: ⊢print(“a_is_odd”)
While the tab character is allowed, spaces are preferred. Many experience Python programmers set their text editors to replace tab characters with four spaces.
Important
Syntax Rule Seven
When using Python interactively, an entirely blank line ends a multi-line compound statement.
Note that if you’re using another editor (BBEdit, TextPad, etc.) you won’t get the same level of automatic help that you get from IDLE. Other tools can provide syntax coloring and remember your indentation, but they don’t all automatically indent when you end a line with a : the way IDLE does.
Often there are several alternatives conditions that need to be handled. We encounter this when we have a series of rules that apply to a situation.
A good example is from Roulette, when we have a spin that could be even, odd or zero. We have a situation like the following.
This is done by adding elif clauses. This is short for “else-if”. We can add an unlimited number of elif clauses. The syntax for the elif clause is almost identical to the initial if clause:
elif expression :
suite
Semantics. Python treats the if and elif sequence of statements as a single, big statement. Python evaluates the if expression first; if it is True, Python executes the if suite and the statement is done; the elif suites are all ignored. If the initial if expression is False, Python looks at each elif statement in order. If an elif expression is True, Python executes the associated suite, and the statement is done; the remaining elif suites are ignored. If none of the elif suites are true, then nothing else happens
Complete Come Out Roll. Here is a somewhat more complete rule for the come out roll in a game of Craps:
d1, d2= random.randint(1,6), random.randint(1,6)
result= None
if d1+d2 == 7 or d1+d2 == 11:
result= "winner"
elif d1+d2 == 2 or d1+d2 == 3 or d1+d2 == 12:
result= "loser"
print(result)
Our if statement has two clauses.
If neither condition is true, the if statement has no effect. The script prints the result, which will be None.
The Roulette Example. Here’s the even-odd rule from Roulette. We have one subtlety in Roulette that we have to look at: the problem of zero and double zero. What we’ll do is generate random numbers between -1 and 36. We’ll treat the -1 as if it was 00, which is like 0, neither even nor odd.
from __future__ import print_function
import random
spin= random.randint(-1,36)
result= None
if spin == 0 or spin == -1:
result= "neither"
elif spin % 2 == 0:
result= "even"
elif spin % 2 == 1:
result= "odd"
print(spin, result)
Our if statement has three clauses.
If none of these conditions is true, the if statement has no effect. The script prints the result, which will be None.
Finally, there is the capability to put a “catch-all” suite at the end of an if statement, which handles all other conditions. This is done by adding an else clause. The syntax for the else clause it somewhat simpler.
else:
suite
This clause is always last and, effectively, always True. When the if expression and all of the elif expressions are false, Python will execute any else suite that we provide.
Come Out Roll Script. Here’s the complete come-out roll rule. In this final example, we’ve added the necessary import and assignment statements to make a complete little script.
comeoutroll.py
from __future__ import print_function
import random
d1,d2= random.randrange(1,7), random.randrange(1,7)
point= None
result= None
if d1+d2 == 7 or d1+d2 == 11:
result= "winner"
elif d1+d2 == 2 or d1+d2 == 3 or d1+d2 == 12:
result= "loser"
else:
point= d1+d2
result= "point is", point
print(result)
Here, we used the else suite to handle all of the other possible rolls. There are six different values (4, 5, 6, 8, 9, or 10), a tedious typing exercise if you write it our using or. We summarize this complex condition with the else clause.
Tip
Debugging the if statement.
If you are typing an if statement, and you get a SyntaxError: invalid syntax, you omitted the :.
A common problem with if statements is an improper condition. You can put any expression in the if or elif statement. If the expression doesn’t have a boolean value, Python will use the bool() function to determine if the expression amounts to True or False. It’s far better to have a clear boolean expression rather than trust the rules used by the bool() function.
One of the more subtle problems with the if statement is being absolutely sure of the implicit condition that controls the else clause. By relying on an implicit condition, it is easy to overlook gaps in your logic.
Consider the following complete if statement that checks for a winner on a field bet. A field bet wins on 2, 3, 4, 9, 10, 11 or 12. The payout odds are different on 2 and 12.
outcome= 0
if d1+d2 == 2 or d1+d2 == 12:
outcome= 2
print("field pays 2:1")
elif d1+d2==4 or d1+d2==9 or d1+d2==10 or d1+d2==11:
outcome= 1
print("field pays even money")
else:
outcome= -1
print("field loses")
Here’s the subtle bug in this example. We test for 2 and 12 in the first clause; we test for 4, 9, 10 and 11 in the second. It’s not obvious that a roll of 3 is missing from the “field pays even money” condition. This fragment incorrectly treats 3, 5, 6, 7 and 8 alike in the else:.
While the else: clause is used commonly as a catch-all, a more proper use for else: is to raise an exception because a condition was found that did not match by any of the if or elif clauses.
Once in a while you may have a situation where the logic is kind of tangled, and you want to say something like the following:
if a > 12:
do nothing
elif a == 0:
print(“zero”)
else:
print(“a between 1 and 12”)
Unfortunately, the Python languages doesn’t allow a suite of statements to be empty. We don’t want to have to rearrange our program’s logic to suit a limitation of the language. We want to express our processing clearly and precisely. Enter the pass statement.
The syntax is trivial.
pass
The pass statement does nothing. It is essentially a syntax place-holder that allows us to have a “do nothing” suite embedded in an if statement.
Here’s how it looks.
if a > 12:
pass
elif a == 0:
print("zero")
else:
print(a, "between 1 and 12")
If the value of a is greater than 12, the if statement’s expression is true, and Python executes the first suite of statements. That suite is simply pass, so nothing happens.
If the value of a is zero, the first elif statement’s expression is true, and Python executes the second suite of statements. That suite is a print() function, and we see a “zero” printed.
If none of the previous expressions are true, Python falls back to the else statement, in which case, we would see a message about a being between 1 and 12.
Sort Three Numbers.
This is an exercise in constructing if-statements. Using only simple variables and if statements, you should be able to get this to work; a loop is not needed.
Given 3 numbers (X, Y, Z)
Assign variables x, y,
z so that
and x,
y, and z are from
X, Y, and
Z. Use only a series of if-statements and
assignment statements.
Hint. You must define the conditions under which you choose between x = X, x = Y or x = Z. You will do a similar analysis for assigning values to y and z. Note that your analysis for setting y will depend on the value set for x; similarly, your analysis for setting z will depend on values set for x and y.
Come Out Roll.
Accept d1 and d2 as input. First, check to see that they are in the proper range for dice. If not, print a message.
Otherwise, determine the outcome if this is the come out roll. If the sum is 7 or 11, print winner. If the sum is 2, 3 or 12, print loser. Otherwise print the point.
Field Roll.
Accept d1 and d2 as input. First, check to see that they are in the proper range for dice. If not, print a message.
Otherwise, check for any field bet pay out. A roll of 2 or 12 pays 2:1, print “pays 2”; 3, 4, 9, 10 and 11 pays 1:1, print “pays even”; everything else loses, print “loses”
Hardways Roll.
Accept d1 and d2 as input. First, check to see that they are in the proper range for dice. If not, print a message.
Otherwise, check for a hard ways bet pay out. Hard 4 and 10 pays 7:1; Hard 6 and 8 pay 9:1, easy 4, 6, 8 or 10, or any 7 loses. Everything else, the bet still stands.
Partial Evaluation.
This partial evaluation of the and and or operators appears to violate the evaluate-apply principle espoused in Execution – Two Points of View. Instead of evaluating all parameters, these operators seem to evaluate only the left-hand parameter before they are applied. Is this special case a problem? Can these operators be removed from the language, and replaced with the simple if-statement? What are the consequences of removing the short-circuit logic operators?