3b. Prof. Rosenthal’s Additions#

Additions to Chapter 3: Functions: topics that the chapter uses, but does not explain. Read this page after the chapter. The practice questions at the end have answers: try each question first, then open its Answer.

Run this page on Colab

Run the setup cell below first. It downloads thinkpython.py, which lets this page show the errors of some examples without stopping the page.

from os.path import basename, exists

def download(url):
    filename = basename(url)
    if not exists(filename):
        from urllib.request import urlretrieve

        local, _ = urlretrieve(url, filename)
        print("Downloaded " + str(local))
    return filename

download('https://github.com/AllenDowney/ThinkPython/raw/v3/thinkpython.py');

import thinkpython

The three forms of range#

Chapter 3 uses range with one argument: range(SOME_INTEGER) gives the integers 0, 1, 2, ... up to SOME_INTEGER minus 1. For example, this loop displays 0, 1 and 2:

for i in range(3):
    print(i)
0
1
2

range can also take two or three arguments:

Form

The values it gives

range(STOP)

0, 1, 2, ... up to STOP minus 1

range(START, STOP)

START, START + 1, START + 2, ... up to STOP minus 1

range(START, STOP, STEP)

START, START + STEP, START + 2*STEP, ... while the value is before STOP

In all three forms, STOP itself is never one of the values. The sections below show each form.

range(START, STOP)#

With two arguments, the first argument is the value to start at, and the second is the value to stop before. This loop displays the integers from 3 to 6 (it stops before 7):

for i in range(3, 7):
    print(i)
3
4
5
6

range(STOP) is the same as range(0, STOP): when you do not give a start, the start is 0.

range(START, STOP) gives STOP minus START values. So range(3, 7) gives 4 values.

If START is equal to STOP or greater than STOP, the range is empty, and the body of the loop does not run. Here, the loop displays nothing; only the last line displays something:

for i in range(5, 5):
    print(i)
print('The loop is done.')
The loop is done.

To include STOP in the values, use STOP plus 1 as the second argument. This loop displays 1 to 5:

for i in range(1, 5 + 1):
    print(i)
1
2
3
4
5

The arguments can be any expressions that have an integer value, such as variables and parameters. This function displays the integers from low to high, including high:

def print_numbers(low, high):
    for i in range(low, high + 1):
        print(i)

print_numbers(8, 11)
8
9
10
11

range(START, STOP, STEP)#

With three arguments, the third argument is the step: the amount to add to get the next value. This loop displays the even numbers from 0 to 8:

for i in range(0, 10, 2):
    print(i)
0
2
4
6
8

The last value is 8, because the next value, 10, is not before STOP. The last value is not always STOP minus 1. Here, it is 7:

for i in range(1, 10, 3):
    print(i)
1
4
7

range(START, STOP) is the same as range(START, STOP, 1): when you do not give a step, the step is 1.

Counting down: a negative step#

When STEP is negative, the values go down, and the range stops before it gets to STOP. This loop counts down from 5 to 1:

for i in range(5, 0, -1):
    print(i)
print('Liftoff!')
5
4
3
2
1
Liftoff!

Chapter 3 uses this form to count down from 99 to 1: range(99, 0, -1).

To include 0, the stop must be one step past it, which is -1. This loop displays 3, 2, 1 and 0:

for i in range(3, -1, -1):
    print(i)
3
2
1
0

With a negative step, START must be greater than STOP. If it is not, the range is empty. This loop displays nothing, because you cannot count down from 1 to 5:

for i in range(1, 5, -1):
    print(i)
print('The loop is done.')
The loop is done.

Arguments that range does not accept#

The arguments of range must be integers. A float, even one like 2.0, causes a TypeError:


for i in range(2.0):
    print(i)
TypeError: 'float' object cannot be interpreted as an integer

The step cannot be 0, because the values would never get to STOP. A step of 0 causes a ValueError:


for i in range(1, 10, 0):
    print(i)
ValueError: range() arg 3 must not be zero

Practice questions#

Question 1 (easy): what is displayed?#

Predict what this code displays. Then run the cell to check (on the website, click Show code cell output).

for i in range(2, 6):
    print(i)

Hide code cell output

2
3
4
5

Question 2 (easy): what is displayed?#

Predict what this code displays. Then run the cell to check (on the website, click Show code cell output).

for i in range(10, 20, 4):
    print(i)

Hide code cell output

10
14
18

Question 3 (medium): what is displayed?#

Predict what this code displays. Then run the cell to check (on the website, click Show code cell output).

for i in range(10, 0, -3):
    print(i)

Hide code cell output

10
7
4
1

Question 4 (medium): what is displayed?#

Predict what this code displays. Then run the cell to check (on the website, click Show code cell output).

for i in range(7, 3):
    print(i)
print('done')

Hide code cell output

done

Question 5 (medium): write the range call#

For each list of values, write a call to range that gives these values, in this order:

  • Part a: 1, 2, 3, 4, 5, 6

  • Part b: 5, 10, 15, 20

  • Part c: 20, 15, 10, 5

  • Part d: -3, -2, -1, 0

Test each call with a for loop that displays the values.

Question 6 (medium): write a function#

Write a function called count_down that takes an integer n and displays the integers from n down to 1, each on its own line, and then displays Go!. For example, count_down(3) displays:

3
2
1
Go!

Start from this header (replace ... with the body):

def count_down(n):
    ...

Question 7 (hard): write a function#

Write a function called print_multiples that takes two integers, n and count, and displays the first count multiples of n (n, 2*n, 3*n, …), each on its own line. For example, print_multiples(7, 4) displays 7, 14, 21 and 28.

Use a range with three arguments. Start from this header (replace ... with the body):

def print_multiples(n, count):
    ...

Question 8 (hard): find the error#

This function should display the integers from high down to low, including both. For example, print_down(5, 2) should display 5, 4, 3 and 2. But it displays nothing. Explain why, and fix it.

def print_down(high, low):
    for i in range(high, low):
        print(i)

print_down(5, 2)

Credits#

Additions by Prof. Y. Rosenthal, for Think Python: 3rd Edition by Allen B. Downey. Text license: Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International