# Making Decisions in our programs¶

Read time: 30 minutes (7531 words)

Text: Chapter 4

Programming involves lots of decisions and loops, we need to examine how Python handles these common concepts!

## Decision making¶

Decisions are at the heart of most interesting programs. You examine data and decide what to do based on what your program finds.

### Basics of making decisions¶

Computers can only ask simple questions. Oddly enough, those questions must be in the form of simple True or False questions. Nothing else is allowed. Most of our more interesting statement types use the answers to such questions to decide how to operate.

The foundation of all question asking in computers is a simple comparison of two data items. The two items must be of the same type to make any sense! With that done, many of the comparisons involve numerical comparisons. For example, if we subtract item one from item two what result might we get?

 negative item one was larger than item two zero item one was identical to item two positive item one was smaller than item two

So, if we can check these simple conditions, we can form basic logical comparisons that will result in a True or False answer. We have come up with a set of standard comparisons, and Python has them as well!

#### Comparison operators¶

Here are the basic operators, they should be easy enough to figure out. (They are similar to those used in many programming languages).

 > greater than >= greater or equal < less than <= less or equal == equal to != not equal to not invert the comparison

We can also use another operator to reverse the boolean value of these expressions:

test = 5 > 10           # results in False
test = not (5 > 10)     # results in True


#### What can be checked?¶

It should be obvious that we can compare numbers with these operators. Can we check anything else?

vara = 'Good'
if vara == 'Good':
print('We have a good string')
if varb != 'Good':


Strings can be compared with the relational operators, and the result is based on alphabetic order:

>>> vara = 'junk'
>>> varb = 'liver'
>>> vara < varb
True


## The if-then-else statement¶

There are places where these questions are asked inside other statements. The most common is probably the if-thenelse statement:

if question:
else:


Warning

In this statement, indenting is how we show what code we want to execute in each part. Python is especially picky about indenting. This is a good habit to acquire for other languages where the indenting is not required, but encourages!

In the spot where question is found, we can either place an expression that evaluates to True or False, or place a variable that has a boolean value in it!

>>> vara = 5
>>> varb = 10
>>> vara > varb
False
>>> varb > vara
True
>>> vara == varb
False
>>> answer = vara > varb
...     print "I got a True"
... else:
...     print "I got a False"
...
I got a False
>>> if vara > varb:
...     print "I got a True"
... else:
...     print "I got a False"
...
I got a False
>>>


This allows us to set up questions as we wish. Which one do you choose? Which ever one that makes you program the clearest!

### The else part is optional¶

In many cases, you only need to do something if the value of your expression is true. In this case the else part can be left off:

if income > bills:
print('Put something in savings!')


### Combining logical values¶

There are a few more operators available that let you ask more complex questions. These involve the logical operations. The most common are and and or which work as you might suspect based on your knowledge of English.

If one thing is true and another thing is false what can you say about both of them? The answer can be figured out using a simple scheme known as a truth table.

#### Truth tables¶

A truth table lists all possible inputs on for the variables, and show the result of the operator.

Here are the rules for the and operator:

 A B A and B False False False True False False False True False True True True

And, here are the rules for the or operator:

 A B A or B False False False True False True False True True True True True

So we see that A and B is only True if both A and B are True, and A or B is True if either A or B is True (or both are True). These can be used to create interesting questions.

>>> varA = True
>>> varB = False
>>> varA and varB
False
>>> varA or varB
True
>>> (6 > 3) or (6 < 3)
True
>>> varA = 10
>>> varA > 0 and varA < 20
True
>>>


We can use parentheses to build up even bigger questions, but I will leave that for your experimentation!

### Short circuits¶

These are usually bad, especially if you are wiring a house. In programming, they are a good thing.

What is the value of 10 / 0? Let’s see:

>>> 10 / 0
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ZeroDivisionError: division by zero


Looks like a problem. What if we want to divide by a variable, but only if the variable is not zero?

The and and or operators stop processing as soon as they know what the answer will be.

• For the and, if the first part ends up False, stop
• For the or, if the first part is True, stop

This can be handy:

if x != 0 and 10/x:
# do something


In this statement, if x has a value of zero, the first part of the logical expression ends up False, so we do not evaluate the second part, and we avoid the error! .

Let’s work through an example!

You are in school, so you just know that someone is going to assign a letter grade for your courses. Let’s see if we can build a simple program to figure out what grade to assign.

### What would a student do?¶

Probably this:

# Student's view of grading

grade = input('Enter the final average: ')
grade = int(grade)  # need to convert the string to an integer

print('You got an ',letter_grade, 'in this course!')


Looks pretty good, I suspect you are thinking. (Actually, most of you would eliminate the test and just assign the grade. Sorry, that is not allowed!)

So, how will this work?

If you enter any grade with a numerical value of zero of higher, you get an A, otherwise you flunked the course. (How could that happen!)

### Watch for common mistakes¶

What is wrong with this test?

if grade >= 0 or grade <= 100:


Think about it. The first test allows any number greater than or equal to zero to be legal, the second on lets any number less than or equal to 100 be legal as well. If we combine these two tests with an or, any number ends up being legal. That is not what we want.

### Keep it simple!¶

We could try this one, which is way too complicated! It sets up a logical variable that is used to decide if the entered grade is legal.

is_legal = True
is_legal = False
is_legal = False
if not is_legal:


That not reverses the value of what comes next (a logical value).

### Stopping the code if the value is illegal¶

At this point, we know the grade is legal. But how do we keep from computing the letter grade if the average is illegal?

Well, we could wrap up the calculation in an else statement (indenting correctly, of course. There is another way:

import sys

sys.exit()


Now we need to figure out the letter grade the “real way!

if grade >= 90:


This will work fine. We already know the grade is not above 100, so any grade from 90-100 will get an ‘A’. What about everything else?

Try this:

if grade >= 80:


If we add this code after the first test, what will happen? You should see that this is wrong. If the grade is 95, this test is still going to be satisfied, so we will end up with a ‘B’. The solution is to only do this test if the first one fails:

if grade >= 90:
else:


I suspect you can see how to complete this code.

Notice anything annoying? If we keep adding tests for the other grades, the code will be sliding off to the right, and that looks bad. Python has a variation for this situation called the elif clause:

if grade >= 90:
...
else:


This looks much better.

### Hmmm, Santa just stopped by!¶

Santa says that if you are on the “nice” list (meaning you have an attendance average above 75%, you get the next letter grade if you are within two points of the boundary. How would we add this feature into the code?

Well, we could go into our code and change all the number, but what if Santa decides to change the number from 2 to 3 (or even 1 on a bad day)? It would be better to use a santa_factor to change the code. We could set this at the top of the program, or even read it in. Here is what we might do:

if grade >= (90 - santa_factor):
`