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 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 |
|---|---|
|
|
|
|
|
|
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)
Answer
The loop displays 2, 3, 4 and 5, each on its own line. The range starts at 2 and stops
before 6.
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)
Answer
The loop displays 10, 14 and 18. Each value is 4 more than the one before it.
The next value would be 22, which is not before 20, so the range stops after 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)
Answer
The loop displays 10, 7, 4 and 1. The step is -3, so each value is 3 less than the one before it.
The next value would be -2, which is past the stop, 0, so the range stops after 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')
Answer
Only done is displayed. The step is 1 (the default), so the range counts up from 7. But 7 is not
before 3, so the range is empty and the body of the loop never runs.
To count down from 7 to 4, use a negative step: range(7, 3, -1).
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, 6Part b:
5, 10, 15, 20Part c:
20, 15, 10, 5Part d:
-3, -2, -1, 0
Test each call with a for loop that displays the values.
Answer
Part a:
range(1, 7). The stop is one more than the last value.Part b:
range(5, 21, 5). Any stop from21to25gives the same values, but21(the last value plus 1) shows the last value most clearly.Part c:
range(20, 4, -5). Any stop from0to4gives the same values.Part d:
range(-3, 1). The arguments can be negative.
For example, this loop tests Part c:
for i in range(20, 4, -5):
print(i)
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):
...
Answer
def count_down(n):
for i in range(n, 0, -1):
print(i)
print('Go!')
The stop is 0, so the last value is 1. The call print('Go!') is not indented under the for
header, so it runs once, after the loop.
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):
...
Answer
def print_multiples(n, count):
for i in range(n, n * count + 1, n):
print(i)
The range starts at n and adds n each time. The last multiple is n * count; the stop is one more
than that, so that the last multiple is included.
Another way uses a range with one argument and multiplies:
def print_multiples(n, count):
for i in range(count):
print(n * (i + 1))
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)
Answer
The range has no step, so the step is 1, and the range counts up from high. Because high is greater
than low, the range is empty and the loop body never runs.
The fix uses a step of -1, and a stop one step past low, so that low is included:
def print_down(high, low):
for i in range(high, low - 1, -1):
print(i)
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