LambdaLabTM
Computer Science · Class 11 · Python Modules
ModulesPrograms⏱️ 16 min read

Programs with Modules

Seven programs that put the three modules to work alongside everything else this course has built — tuples, dictionaries, loops and f-strings. This is also the last page of the Class 11 course, so each one deliberately uses more than the module it is showing off.

1Program 1 — the full marks report

📋 The problem

Print a complete summary of a tuple of marks: count, highest, lowest, and the three averages.

marks_report.py
import statistics

marks = (72, 65, 88, 91, 54, 65, 77)

print('How many :', len(marks))
print('Highest  :', max(marks))
print('Lowest   :', min(marks))
print('Mean     :', round(statistics.mean(marks), 2))
print('Median   :', statistics.median(marks))
print('Mode     :', statistics.mode(marks))
Output
How many : 7
Highest  : 91
Lowest   : 54
Mean     : 73.14
Median   : 72
Mode     : 65

Six lines that would have taken sixty a chapter ago — the champion loops, the total-and-divide, and the frequency dictionary are all in there, written by somebody else.

2Program 2 — who is above the class mean?

A dictionary of names and marks, and the two-pass shape: work the summary out, then walk the data again with it.

class_summary.py
import statistics

scores = {'Riya': 78, 'Amit': 85, 'Sara': 62, 'John': 91, 'Zoya': 85}
values = tuple(scores.values())

print('Mean  :', round(statistics.mean(values), 2))
print('Median:', statistics.median(values))
print('Mode  :', statistics.mode(values))

for name, s in scores.items():
    if s > statistics.mean(values):
        print(name, 'is above the class mean')
Output
Mean  : 80.2
Median: 85
Mode  : 85
Amit is above the class mean
John is above the class mean
Zoya is above the class mean
values = tuple(scores.values())

statistics.mean() is happy with .values() as it is; the tuple() is here so the same values can be handed to all three calls and read back if needed.

for name, s in scores.items():

The names are part of the answer, so it has to be .items() — .values() would leave you with a number and nobody to attach it to.

Tip
Calling statistics.mean() inside the loop is wasteful. It works out the same answer five times over. Store it once above the loop — avg = statistics.mean(values) — and compare against avg. On five students it makes no measurable difference; the habit is what matters, and it is the same habit as not calling rolls.count(r) once per item.

3Program 3 — a table of circle areas

circle_table.py
import math

radii = (1, 2.5, 7, 10)

for r in radii:
    area = math.pi * r * r
    print('r =', r, '-> area', round(area, 2))
Output
r = 1 -> area 3.14
r = 2.5 -> area 19.63
r = 7 -> area 153.94
r = 10 -> area 314.16

A tuple of radii, one loop, one formula. The tuple can hold whole numbers and decimals side by side, because a tuple never cared what type its items were.

4Program 4 — rolling a die sixty times

📋 The problem

Roll a die 60 times, tally the faces, and draw the result as a bar chart.

Everything on this page so far has come from the modules. This one is the dictionary tally, the sorted walk and string replication all at once — with random supplying the data.

dice_experiment.py
import random

freq = {}

for i in range(60):
    face = random.randint(1, 6)
    freq[face] = freq.get(face, 0) + 1

for face in sorted(freq):
    print('Face', face, ':', freq[face], '*' * freq[face])
Output
Face 1 : 11 ***********
Face 2 : 10 **********
Face 3 : 11 ***********
Face 4 : 11 ***********
Face 5 : 10 **********
Face 6 : 7 *******
freq[face] = freq.get(face, 0) + 1

The frequency tally, unchanged from the dictionary chapter. It does not care that the numbers are arriving from random rather than from a tuple.

for face in sorted(freq):

Without sorted() the faces come out in the order they were first rolled, which is different on every run and reads as noise.

'*' * freq[face]

String replication makes the bar. Eleven stars for eleven rolls — the chart is the count, drawn.

Note
Sixty rolls is not enough to look fair, and it should not be. This run gave six sixes fewer than ones. Ten rolls each would be the honest expectation, and real randomness wanders around it. Raise the 60 to 6000 and the six bars come out close to equal — that is how you check a random program, not by staring at one short run.
dice_experiment.py

5Program 5 — cartons for an order list

packing_cartons.py
# every part-full carton still costs a whole carton

import math

orders = (('pens', 47), ('books', 12), ('bags', 100))
per_carton = 6

for item, qty in orders:
    print(item, ':', qty, 'units ->', math.ceil(qty / per_carton), 'cartons')
Output
pens : 47 units -> 8 cartons
books : 12 units -> 2 cartons
bags : 100 units -> 17 cartons

A tuple of records unpacked in the loop header, and math.ceil() doing the one thing it is for. Note books: 12 ÷ 6 is exactly 2, and ceil() leaves an exact answer alone — it only ever rounds up something that is not already whole.

6Program 6 — the distance between two points

distance.py
import math

x1, y1 = 2, 3
x2, y2 = 7, 15

d = math.sqrt(math.pow(x2 - x1, 2) + math.pow(y2 - y1, 2))

print('Distance:', d)
Output
Distance: 13.0

x1, y1 = 2, 3 is packing and unpacking in one line — the right-hand side builds the tuple (2, 3) and the left-hand side takes it apart. Two lines of setup instead of four, and the pairing of x with y is visible.

7Program 7 — compound interest

📋 The problem

₹25,000 invested at 7.5% for 5 years, compounded yearly. What is it worth?

compound_interest.py
# A = P (1 + r/100) ** n

import math

p = 25000
r = 7.5
n = 5

amount = p * math.pow(1 + r / 100, n)

print('Amount after', n, 'years:', round(amount, 2))
print('Interest earned    :', round(amount - p, 2))
Output
Amount after 5 years: 35890.73
Interest earned    : 10890.73

math.pow(1 + r / 100, n) could equally be (1 + r / 100) ** n — same answer, and the operator is the one to prefer. The rounding is on the way out only: rounding 1.075 first would throw the answer off by rupees.

8Program 8 — the guessing game, with a limit

The game from the random page, with a cap on the tries — so the loop has two ways out and needs the loop's else to tell them apart:

guess_limited.py
# seven guesses is always enough if you halve the range each time

import random

secret = random.randint(1, 100)

for turn in range(1, 8):
    guess = int(input('Guess ' + str(turn) + ': '))

    if guess == secret:
        print('Correct! You took', turn, 'tries.')
        break
    elif guess < secret:
        print('Too low')
    else:
        print('Too high')
else:
    print('Out of guesses. It was', secret)
Output
Guess 1: 50
Too high
Guess 2: 25
Too low
Guess 3: 37
Too low
Guess 4: 43
Too high
Guess 5: 40
Too low
Guess 6: 41
Too low
Guess 7: 42
Correct! You took 7 tries.
Key Takeaway
The else belongs to the for. It runs only when the loop ran out of turns without a break — which is exactly “the player never got it”. The same shape as the “not found” branch of a linear search, doing a different job.

Seven turns is not arbitrary. Halving the range each time — 50, 25, 37, 43, 40, 41, 42 — narrows 100 possibilities to one in at most seven guesses, which is math.ceil(math.log2(100)) if you want to prove it.

9Recap

The modules do not replace the loops

They replace the arithmetic inside them. Every program here still needs a tuple, a dictionary or a for loop of your own.

Work a summary out once

statistics.mean() inside a loop recomputes the same number every round. Store it above the loop.

Round on the way out, not on the way in

Rounding an intermediate value — 1.075 in the interest program — moves the final answer. Round only what you print.

Check a random program over many runs

Sixty rolls look lumpy however fair the die is. Six thousand is what tells you whether the code is right.

✍️ Now write these yourself
  1. 1

    Roll two dice 1000 times and tally the totals. Which total wins, and why?

    Hint · 7 — there are six ways to make it and only one to make 2. Draw it with '*' * (count // 5) so the bars fit.

  2. 2

    Print a report for a dictionary of city temperatures: mean, median, hottest and coldest city by name.

    Hint · statistics on .values(), and the champion loop on .items() for the two names.

  3. 3

    Generate 20 random marks between 0 and 100, then report how many passed and the class mean.

    Hint · Build the tuple in a loop with marks = marks + (random.randint(0, 100),), then summarise it.

  4. 4

    Write a simple quiz: five random addition questions, one mark each, with a score at the end.

    Hint · Two randint calls per question, compare with int(input()), and a counter for the score.

  5. 5

    Print how many buses a school trip needs, for a tuple of (class, strength) rows, at 40 to a bus.

    Hint · Program 5 with the numbers changed — and a total at the end, which is not the same as one ceil() of the grand total.

Quick Check

Why is calling statistics.mean(values) inside the loop wasteful?

Quick Check

In the cartons program, why does 12 units give exactly 2 cartons?

Quick Check

What does the else attached to the for loop do in the guessing game?