Decision Structures
7.1 Simple Decisions
So far, we have mostly viewed computer programs as sequences of instructions that are followed one after the other. Sequencing is a fundamental concept of programming, but alone it is not sufficient to solve every problem. Often it is necessary to alter the sequential flow of a program to suit the needs of a particular situation. This is done with special statements known as control structures. In this chapter, we’ll take a look at decision structures, which are statements that allow a program to execute different sequences of instructions for different cases, effectively allowing the program to “choose” an appropriate course of action.
165
166 Chapter 7. Decision Structures
7.1.1 Example: Temperature Warnings
Let’s start by getting the computer to make a simple decision. For an easy example, we’ll return to the Celsius to Fahrenheit temperature conversion program from Chapter 2. Remember, this was written by Susan Computewell to help her figure out how to dress each morning in Europe. Here is the program as we left it:
# convert.py
# A program to convert Celsius temps to Fahrenheit
# by: Susan Computewell def main():
celsius = eval(input("What is the Celsius temperature? ")) fahrenheit = 9/5 * celsius + 32
print("The temperature is", fahrenheit, "degrees fahrenheit.") main()
This is a fine program as far as it goes, but we want to enhance it. Susan Computewell is not a morning person, and even though she has a program to convert the temperatures, sometimes she does not pay very close attention to the results. Our enhancement to the program will ensure that when the temperatures are extreme, the program prints out a suitable warning so that Susan takes notice.
The first step is to fully specify the enhancement. An extreme temperature is either quite hot or quite cold. Let’s say that any temperature over 90 degrees Fahrenheit deserves a heat warning, and a temperature under 30 degrees warrants a cold warning. With this specification in mind, we can design an enhanced algorithm.
Input the temperature in degrees Celsius (call it celsius) Calculate fahrenheit as 9/5 celsius + 32
Output fahrenheit if fahrenheit > 90
print a heat warning if fahrenheit < 30
print a cold warning
This new design has two simple decisions at the end. The indentation indicates that a step should be performed only if the condition listed in the previous line is met. The idea here is that the decision introduces an alternative flow of control through the program. The exact set of steps taken by the algorithm will depend on the value of fahrenheit.
Figure 7.1 is a flowchart showing the possible paths that can be taken through the algorithm.
The diamond boxes show conditional decisions. If the condition is false, control passes to the next statement in the sequence (the one below). If the condition holds, however, control transfers to the instructions in the box to the right. Once these instructions are done, control then passes to the next statement.
7.1. Simple Decisions 167
yes
no
yes
no fahrenheit < 30?
fahrenheit > 90?
Print a Heat Warning
Print a Cold Warning Print Fahrenheit
Farenheit = 9/5 * celsius + 32 Input Celsius Temperature
Figure 7.1: Flowchart of temperature conversion program with warnings.
Here is how the new design translates into Python code:
# convert2.py
# A program to convert Celsius temps to Fahrenheit.
# This version issues heat and cold warnings.
def main():
celsius = eval(input("What is the Celsius temperature? ")) fahrenheit = 9/5 * celsius + 32
print("The temperature is", fahrenheit, "degrees Fahrenheit.")
# Print warnings for extreme temps if fahrenheit > 90:
print("It’s really hot out there. Be careful!") if fahrenheit < 30:
print("Brrrrr. Be sure to dress warmly!") main()
You can see that the Python if statement is used to implement the decision.
The form of the if is very similar to the pseudocode in the algorithm.
if <condition>:
168 Chapter 7. Decision Structures
<body>
The body is just a sequence of one or more statements indented under the if heading. In convert2.py there are two if statements, both of which have a single statement in the body.
The semantics of the if should be clear from the example above. First, the condition in the heading is evaluated. If the condition is true, the sequence of statements in the body is executed, and then control passes to the next statement in the program. If the condition is false, the state-ments in the body are skipped. Figure 7.2 shows the semantics of the if as a flowchart. Notice
<Statement>
<Statement>
<Statement>
yes
no
. . .
<condition> true?
Figure 7.2: Control flow of simple if-statement .
that the body of the if either executes or not depending on the condition. In either case, control then passes to the next statement after the if. This is a one-way or simple decision.
7.1.2 Forming Simple Conditions
One point that has not yet been discussed is exactly what a condition looks like. For the time being, our programs will use simple conditions that compare the values of two expressions.
<expr> <relop> <expr>
<relop>is short for relational operator. That’s just a fancy name for the mathematical concepts like
“less than” or “equal to.” There are six relational operators in Python, shown in the following table.
7.1. Simple Decisions 169 Python Mathematics Meaning
< < Less than
<= ≤ Less than or equal to
== = Equal to
>= ≥ Greater than or equal to
> > Greater than
! = 6= Not equal to
Notice especially the use of== for equality. Since Python uses the = sign to indicate an assignment statement, a different symbol is required for the concept of equality. A common mistake in Python programs is using= in conditions, where a == is required.
Conditions may compare either numbers or strings. When comparing strings, the ordering is lexicographic. Basically, this means that strings are put in alphabetic order according to the underlying Unicode values. So all upper-case Latin letters come before lower case equivalents (e.g., “Bbbb” comes before “aaaa”, since “B” precedes “a”).
I should mention that conditions are actually a type of expression, called a Boolean expression, after George Boole, a 19th century English mathematician. When a Boolean expression is eval-uated, it produces a value of either true (the condition holds) or false (it does not hold). Some languages such as C++ and older versions of Python just use the ints 1 and 0 to represent these values. Other languages like Java and modern Python have a dedicated data type for Boolean expressions.
In Python, Boolean expressions are of type bool and the Boolean values true and false are represented by the literals True and False. Here are a few interactive examples:
>>> 3 < 4
Back in Chapter 1, I mentioned that there are several different ways of running Python programs.
Some Python module files are designed to be run directly. These are usually referred to as “pro-grams” or “scripts.” Other Python modules are designed primarily to be imported and used by other programs; these are often called “libraries.” Sometimes we want to create a sort of hybrid module that can be used both as a stand-alone program and as a library that can be imported by other programs.
170 Chapter 7. Decision Structures So far, most of our programs have had a line at the bottom to invoke the main function.
main()
As you know, this is what actually starts a program running. These programs are suitable for running directly. In a windowing environment, you might run a file by (double-)clicking its icon.
Or you might type a command like python <myfile>.py.
Since Python evaluates the lines of a module during the import process, our current programs also run when they are imported into either an interactive Python session or into another Python program. Generally, it is nicer not to have modules run as they are imported. When testing a program interactively, the usual approach is to first import the module and then call its main (or some other function) each time we want to run it.
In a program designed to be either imported (without running) or run directly, the call to main at the bottom must be made conditional. A simple decision should do the trick.
if <condition>:
main()
We just need to figure out a suitable condition.
Whenever a module is imported, Python sets a special variable in the module called __name__
to be the name of the imported module. Here is an example interaction showing what happens with the math library:
>>> import math
>>> math.__name__
’math’
You can see that, when imported, the __name__ variable inside the math module is assigned the string ’math’.
However, when Python code is being run directly (not imported), Python sets the value of __name__to be ’__main__’. To see this in action, you just need to start a Python shell and look at the value.
>>> __name__
’__main__’
So, if a module is imported, the code in that module will see a variable called __name__ whose value is the name of the module. When a file is run directly, the code will see that __name__ has the value ’__main__’. A module can determine how it is being used by inspecting this variable.
Putting the pieces together, we can change the final lines of our programs to look like this:
if __name__ == ’__main__’:
main()
This guarantees that main will automatically run when the program is invoked directly, but it will not run if the module is imported. You will see a line of code similar to this at the bottom of virtually every Python program.