In this topic students learn to generate random numbers and make random
choices, using the random module.
Be able to read, comprehend, trace, adapt and create Python code that:
random module, and imports a single tool from itrandintchoicerandrangeThis chapter was written for Dodona from new material by the course author, after the rest of the course had been converted, so it has no deck of its own. The author’s Intermediate Python series has a Numbers deck that covers the random-numbers half of this chapter with different examples (it also covers data types, casting and modulo, both taught elsewhere in this course): on Google Slides. A PDF copy is kept on Dodona too.
Random numbers are the first thing in this course that makes a program behave differently on two runs with the same input. That is what makes them motivating (dice, cards, guessing games) and also what makes them awkward to reason about: there is no single right output to predict. The predict and run activity handles this by asking for the set of possible outputs, the lowest, the highest and anything that can never appear, rather than a specific number.
The chapter introduces three tools, one per theory page. randint comes first
because its two arguments read naturally as “lowest” and “highest”. choice
follows because it builds directly on the previous chapter’s lists, and
randrange comes last because it builds on range, including the step.
import random goes at the top of the program, and every tool is then
written as random. followed by its name. from random import randrange
imports one tool, which is then written on its own.random.randint(a, b) includes both a and b.random.choice(list) picks one item and leaves the list unchanged, so the
same item can come up again.randrange(start, stop, step) picks one of the values range would count
through, so, like range, it never picks the stop value.str() before it is
joined onto text.range(1, 10) stops at 9 tend to assume randint(1, 10) does too. It does
not, while randrange(1, 10) does. The Investigate task’s “why not (0, 6)?”
question is a good place to have students say out loud which end is
included.from random import randrange followed by
random.randint(...) fails with a NameError, and so does a bare
randint(...) after import random.randint call inside the loop picks a new secret number
after every guess, and the game becomes nearly unwinnable. Ask students what
the secret number is on the second time round the loop.>= and <=. The tests include guesses exactly 5 and
exactly 6 away on both sides.Every exercise in this chapter uses random numbers, so the tests set a fixed
seed before each student program runs: the same seed always gives the same
sequence of random numbers, so the tests know the secret number or the hand of
cards in advance, and feed in guesses chosen for it. This only works when the
student’s program asks for random numbers the same way the model solution does,
which is why each exercise description names the call to use and when to make
it (once, after the mode is chosen; value before suit on every card). Calls that
are equivalent for the same seed are accepted: randrange(1, 101) for
randint(1, 100), and card_values[random.randint(0, 12)] for
random.choice(card_values).
A student whose program works when they play it but fails the tests has usually made a random call in a different order or place from the one the description asks for. The descriptions explain seeding in a callout, and that is worth pointing to rather than debugging the game logic.