Standard Library Tools: Math and Randomness
Learning Objectives
- You can use selected functions from
math. - You can use
random.choice,random.randint, andrandom.seedin small programs. - You can explain why random programs are tested differently from deterministic programs.
- You can keep randomness near the edge of a program so helper functions remain testable.
The standard library is full of small tools. This chapter focuses on two modules: math and random.
The math module contains mathematical functions and constants:
import math
print(math.sqrt(81))print(math.ceil(4.2))print(math.floor(4.8))print(math.pi)Some operations, such as addition and multiplication, are built into Python’s operators. Other operations live in math. The module keeps the less common mathematical tools out of the core language but available when needed.
Square root call
0 / 5 points
After import math, which expression calculates the square root of 81?
A Small math Example
Imagine a study log extension that compares two kinds of work: reading minutes and practice minutes. You might want a single “effort length” that combines both values. One possible calculation is:
import math
def effort_length(reading_minutes, practice_minutes): return math.sqrt(reading_minutes ** 2 + practice_minutes ** 2)
print(effort_length(30, 40))This prints 50.0. The formula is not important for the course. The library-use pattern is: import the module, call the function through the module name, and return the result from your own helper.
Distance between two points
0 / 10 points
Define a function named point_distance(x1, y1, x2, y2).
The function should return the distance between the points (x1, y1) and (x2, y2). Use this formula:
math.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2)For example, point_distance(0, 0, 3, 4) should return 5.0.
Use the math module and math.sqrt(...) in your solution. Do not ask for user input and do not print inside the function.
Calculation and Presentation
Some math functions are about calculation. Others are often used when preparing a value for display.
import math
minutes = 125hours = minutes / 60
print(hours)print(math.floor(hours))print(math.ceil(hours))math.floor(2.08...) gives 2; math.ceil(2.08...) gives 3. Neither is “the correct way” to display time by itself. It depends on what you mean.
For the study log, 125 minutes is probably better displayed as 2 hours 5 minutes than as 2.0833333333 hours, 2 rounded-down hours, or 3 rounded-up hours. That is a design choice. The library supplies tools; your program chooses the representation that tells the truth most clearly.
This distinction appears again with pandas. A library can compute an average with many decimal places. Your dashboard still decides whether to print 43.3333333333, 43.3, or about 43.
Random Choices
The random module contains tools for randomness:
import random
subjects = ["math", "history", "programming"]print(random.choice(subjects))print(random.randint(1, 6))random.choice(subjects) returns one item from the list. random.randint(1, 6) returns a random integer from 1 through 6, including both endpoints.
Randomness is useful when the program should vary: choosing a review subject, simulating a die roll, shuffling practice questions, or sampling data. But randomness also makes testing harder, because the exact answer can change from run to run.
Seeding Randomness
Random number generators in programming are usually pseudo-random. They produce values that look random, but they follow a deterministic sequence from an initial value called a seed.
import random
random.seed(5)print(random.randint(1, 6))print(random.randint(1, 6))If you run the same program again with the same seed, you get the same sequence. In this example, the two calls produce 5 and 3 every time. This is useful for examples, debugging, and tests.
Do not call random.seed(...) everywhere. Put it in tiny experiments or tests when you need repeatability. In a real program, you usually let the generator vary naturally.
Seeded random integers
0 / 5 points
What does this print each time the complete program is run?
import randomrandom.seed(5)print(random.randint(1, 6))print(random.randint(1, 6))Pick a review subject
0 / 10 points
Define a function named pick_review_subject(subjects).
- If
subjectsis empty, returnNone. - Otherwise, return one item chosen with
random.choice(subjects).
Import the module with import random and call the function through the module name, as random.choice(subjects). The tests rely on this form.
Do not ask for user input. The exact non-empty result is random, but it must be one of the original subjects.
Do not print inside the function.
Seeding Is a Boundary Choice
It is tempting to put a seed inside the helper function:
def choose_review_subject(subjects): random.seed(1) return random.choice(subjects)This makes the function repeatable, but it also makes it less random. Every call starts the generator from the same place. Depending on the list, it may choose the same subject again and again.
A better pattern is to keep the helper honest and let tests control the random behavior from outside when they need to:
random.seed(1)subject = choose_review_subject(subjects)Or test a property, as in the next section. The general principle is familiar from earlier parts: keep small helpers focused, and keep special testing setup outside the helper unless it is part of the helper’s real job.
Testing Random Code
There are two common strategies for random code.
First, test the non-random helper separately. If one function chooses a subject and another formats a review message, keep the formatting deterministic:
def review_message(subject): return f"Review {subject} today."That function is easy to test.
Second, test properties rather than exact values. A random die roll should be between 1 and 6. A random subject should be one of the original subjects. A random choice from an empty list should be handled deliberately rather than crashing by surprise.
subject = random.choice(subjects)assert subject in subjectsThat assertion does not know which subject will be chosen. It checks the property that must always be true.
Check a random choice
0 / 5 points
Arrange the lines into a small property check for a random subject choice.
Keep Randomness at the Edge
The study log should not become random at its core. A summary function should return the same total every time for the same input. A function that counts minutes should not call random.
A good pattern is to keep randomness near the user-facing edge:
import random
def choose_review_subject(subjects): if len(subjects) == 0: return None return random.choice(subjects)
def review_message(subject): if subject is None: return "No subjects to review yet." return f"Review {subject} today."Now the random choice is small, and the message logic is deterministic.
Testing random behavior
0 / 10 points
Explain why this assertion is a better test of a random choice than checking for one exact subject:
subject = random.choice(subjects)assert subject in subjectsWrite a short explanation (about 2-3 sentences).
Randomness and the Study Log
Randomness is not central to the study log, but it can be useful around the edges. For example, the program might suggest a review subject based on subjects you have studied before:
def unique_subjects(sessions): subjects = [] for session in sessions: subject = session.subject if subject not in subjects: subjects.append(subject) return subjectsThen:
subjects = unique_subjects(sessions)review_subject = choose_review_subject(subjects)print(review_message(review_subject))Notice the separation. unique_subjects is deterministic. choose_review_subject is random. review_message is deterministic. Keeping those roles separate makes the random part small enough to reason about.
Check Your Understanding
- Why is
math.sqrt(25)clearer than importing everything frommath? - What does
random.choice(subjects)return? - Why can a random function be hard to test with one exact expected output?
- What does it mean to test a property of a random result?
AI Study Aid
Create a chapter diagram
We're looking into to what extent AI-generated diagrams could help with studying.
Use this study aid to generate an AI-generated visual summary of the material you just studied.
Each diagram style emphasizes the content in a different way, so you can choose the focus
that feels most useful.
Using the diagram generator is voluntary and does not affect your course progress. We encourage
you to try it out and see if it helps, but it's totally up to you! Your answers help us understand
how to make better study aids in the future.