On this page

Decisions

Every program so far has done the same thing each time it ran: every line, top to bottom. This module lets a program look at a value and choose what to do, so that some lines run only some of the time.

Before this, you can: give a value a name and change it; work out an expression by hand; print a value to see it.

By the end you will be able to say whether a comparison is True or False, say which lines of a program will run for a given value, and turn a rule written in words into code and test it at its edges.

Questions with yes-or-no answers

3 + 4 works out to a number. A comparison works out to one of two special values, True or False:

age = 16
print(age > 12)
print(age > 16)
print(age >= 16)
True
False
True

16 is not greater than 16, so the second line is False. It is greater than or equal to 16, so the third is True. Most mistakes with comparisons happen exactly there, at the value on the boundary.

Written Asks
a > b is a greater than b?
a < b is a less than b?
a >= b is a greater than or equal to b?
a <= b is a less than or equal to b?
a == b are they equal?
a != b are they different?

Text can be compared for equality too, and every character counts, including capitals:

print("go" == "go")
print("go" == "Go")
True
False

True and False are values like any other. They can be given a name, and it is common to do so:

age = 15
is_adult = age >= 18
print(is_adult)
False

Python worked out the comparison, got False, and stored that under is_adult. As in the last module, the name holds the answer, not the question.

One equals sign or two?

There are now two things that look alike:

Written Does
age = 16 stores 16 under the name age
age == 16 asks whether age is 16, and works out to True or False

One equals sign changes something. Two equals signs change nothing; they only ask. Using one where two are needed is so common that Python refuses to run the program and tells you which line:

age = 16
if age = 16:
    print("sixteen")
  File "your_program.py", line 2
    if age = 16:
       ^^^^^^^^
SyntaxError: invalid syntax. Maybe you meant '==' or ':=' instead of '='?

Python even suggests the fix. (It also mentions :=, a different sign that this course does not use. You can ignore that part.)

if, and the lines that belong to it

temp = 30
print("checking")
if temp > 25:
    print("hot")
    print("drink water")
print("done")
checking
hot
drink water
done

if is followed by a comparison and a colon. The lines underneath that are indented, pushed in by four spaces, belong to the if. They run only when the comparison is True.

print("done") is not indented, so it does not belong to the if. It runs whatever the temperature is. Here is the same program on a cooler day:

temp = 20
print("checking")
if temp > 25:
    print("hot")
    print("drink water")
print("done")
checking
done

Python reached the if, worked out 20 > 25, got False, skipped the two indented lines and carried on with the next line that was not indented. The program did not stop. It only left something out.

Indentation is not decoration in Python. It is how you say which lines belong together.

Otherwise

Often there are two things to do, one for each answer. else holds the lines for when the comparison is False:

from scimigo import canvas, rectangle, circle

canvas(600, 400)
hour = 21
if hour >= 19:
    rectangle(0, 0, 600, 400, color="midnightblue")
    circle(470, 90, 35, color="lightyellow")
else:
    rectangle(0, 0, 600, 400, color="skyblue")
    circle(470, 90, 45, color="gold")
rectangle(0, 300, 600, 100, color="darkgreen")

Exactly one of the two indented groups runs, never both and never neither. else has no comparison of its own: it means "in every other case". The last line, the ground, is not indented, so it is drawn either way. Change hour to 9 and the first group is skipped and the second runs.

More than two cases

For three or more cases, put elif (short for "else if") between if and else:

size = 12
if size > 20:
    print("large")
elif size > 5:
    print("medium")
else:
    print("small")
medium

Python tries the comparisons from the top and runs the group under the first one that is True. Then it skips all the rest, without even looking at them.

That is why the order matters. size > 5 is also true of 40, but a 40 never gets that far, because size > 20 caught it first. If the two tests were the other way round, every large parcel would be called medium:

size = 40
if size > 5:
    print("medium")
elif size > 20:
    print("large")
else:
    print("small")
medium

The second test can never win. Anything greater than 20 is also greater than 5, and the first test takes it. When you write a chain, start from one end of the range and work towards the other.

Two tests at once

and, or and not join comparisons:

height = 130
has_ticket = False
print(height >= 120 and has_ticket)
print(height >= 120 or has_ticket)
print(not has_ticket)
False
True
True

and is True only when both sides are. or is True when at least one side is. not turns True into False and False into True.

left right left and right left or right
True True True True
True False False True
False True False True
False False False False

In everyday speech "or" often means one or the other but not both. In Python, or is also True when both sides are.

Testing a rule at its edges

A rule such as "under 5 go free" has an edge, and the cases that go wrong are the ones on it. Is a five-year-old free? The words say no. Whether your code says no depends on whether you wrote < or <=.

So when you write a comparison, try the value exactly on the boundary, and one on each side. For "under 5": try 4, 5 and 6. Three runs will tell you more than thirty in the middle of the range.

In the lab

You will predict which lines of a program run before running it, make a sky that changes with the hour, add a third colour to a signal lamp, and write a ticket-price rule that has to be right at every boundary.

Your turn

Now try it yourself

Predict what a program will do, run it, and step through it line by line. The checks tell you when your own code works.

Loading the lab…

In this lab

  1. True or False?

    A comparison works out to True or False. In each program age is 16. Decide what is printed.

  2. One equals sign or two?

    One equals sign stores a value. Two ask a question. Decide what each of these does.

  3. A variable that is True

    The answer to a comparison is a value, and it can be stored under a name like any other.

  4. Which lines run?

    The same program on a hot day and on a cool day. Decide what is printed each time.

  5. Day or night

    The sky in this picture is light blue whatever the hour. Make it "midnightblue" when hour is 20 or later, and leave it "skyblue" before that.

    When you have done it, try hour = 19 and hour = 20. The check tries those too.

  6. First match wins

    This program is meant to call a parcel small, medium or large. A size above 20 should be large; otherwise a size above 5 should be medium; all other sizes should be small. Predict what the broken program prints, then reorder its tests and their matching print lines. Keep the same comparisons. Try sizes 5, 6, 20 and 21.

  7. Signal lamp

    The lamp is green for "go" and red for everything else. Add a third case, so that "wait" shows "yellow".

    Any other signal should still be red. Change the first line to try different signals.

  8. Both, either, not

    A ride needs you to be at least 120 tall and to have a ticket. Each program prints the answer with and, then what the answer would be with or.

  9. Thermometer

    Draw a thermometer for the temperature in temp.

    • The bar is a rectangle 60 wide with its left edge at x = 270. It stands on y = 350 and is temp × 6 pixels tall.
    • Below 10 it is "blue" and labelled cold. From 10 up to 24 it is "green" and labelled mild. At 25 and above it is "red" and labelled hot.
    • The label is written with text, anywhere you like.

    The checks try temperatures on both sides of each boundary.

  10. Ticket price

    Work out the price of a ticket from age and is_student.

    • Children under 5 go free: the price is 0.
    • Anyone under 16 pays 6. So does a student of any age.
    • Everyone else pays 10.

    Print the price: one line with one number. Then write the price on the canvas with text.

    The checks try several ages, with and without is_student.

  11. Parcel label

    A courier charges by weight.

    • Up to and including 2 kg: 5.
    • More than 2 kg, up to and including 10 kg: 9.
    • More than 10 kg, up to and including 30 kg: 15.
    • A fragile parcel costs 3 more.
    • Anything over 30 kg is refused, fragile or not.

    From weight and fragile, print one line: the charge, or the words Too heavy. No picture.

    The checks sit on every boundary.

  12. Inside the box?

    A light green square is drawn from (240, 140) to (360, 260).

    Draw a circle of radius 10 at the point (x, y): "green" if the point is inside the square, "orange" if it is not.

    The left and top edges count as inside. The right and bottom edges do not. So x = 240 is inside and x = 360 is not.

  13. The lamp that is always red

    This lamp should be green for "go", yellow for "wait" and red for anything else. It has two mistakes.

    The first stops the program before it starts: read the message and fix that line. Then run it again. It runs now, but the lamp is the wrong colour for "go". One of the tests can never be True. Find out why, and fix it.

  14. Choose your test values

    Look again at the Parcel label rules. Suppose a friend has written a program for them and asks you to test it. You may only try a few weights.

    Write, as comments, the smallest list of weights that would catch a program with any boundary wrong, and beside each weight the charge you expect.

    There are no checks. Go through the list below when you are done.