As programs grow, one huge file becomes impossible to manage. Modules let you split code into separate files, each focused on one topic — like chapters in a book.
In Python, every .py file is a module. A folder of modules is a package.
📦 Importing modules
You already use modules! Python's standard library is full of them.
import math
print(math.sqrt(16)) # 4.0
from random import choice
print(choice(["a", "b"])) # picks one
💡 Two import styles
import math → use as math.sqrt().
from math import sqrt → use as sqrt() directly.
🧩 Separation of concerns
Each module should handle one concern. A typical small app might split like this:
myapp/
├── data.py # loading & saving
├── logic.py # the rules & calculations
├── display.py # printing to the screen
└── main.py # ties it all together
When the display needs to change, you only touch display.py — the logic stays untouched. This is the heart of good architecture.
🔗 Low coupling, high cohesion
High cohesion: things in one module belong together.
Low coupling: modules don't depend too heavily on each other's inner details — they talk through clean functions.
If changing one file forces you to edit five others, your modules are too tightly coupled. Aim for pieces you can change independently.
✅ What you learned
Split big programs into modules (files) and packages (folders).
Use import to reuse code.
Separation of concerns — one module, one job.
Aim for high cohesion and low coupling.
🎮 Time to Practice!
Organize code and reuse built-in modules. 🗃️
📦
Task 1: Use the math Module
Easy
Import math and print the square root of 16 and 25 → 4.0 then 5.0.
import math
print(math.sqrt(16))
print(math.sqrt(25))
🧩
Task 2: Separate Logic from Display
Medium
Keep the calculation in add_all(numbers) and the wording in show(value) — two separate concerns, two separate functions. Use [4, 5, 6] and print the raw total, then the pretty line.
def add_all(numbers):
return sum(numbers)
def show(value):
return "Total is: " + str(value)
total = add_all([4, 5, 6])
print(total)
print(show(total))
🔧
Task 3: A Tiny Toolbox Module
Medium
Group two related helpers into one class that acts like a "text tools" module: loud(text) returns it in capitals and quiet(text) returns it in lowercase. Print loud("hello") then quiet("HELLO").
Big programs survive because they are built from small, swappable pieces. Practice cutting programs into layers.
📦
Task 4: Borrow From the Standard Library
Easy
Python ships with hundreds of ready-made modules. Import statistics and print the mean, median and mode of [4, 1, 4, 9, 2]. Never write code that already exists!
Random results make testing impossible — unless you seed them. Import random, call random.seed(42), then print three dice rolls. Run it twice: identical every time, which is exactly what tests need.
6
1
1
import random
random.seed(42)
for roll in range(3):
print(random.randint(1, 6))
🧠
Task 6: Logic Layer vs Display Layer
Medium
Split a program in two: calculate_total(prices, tax) that only does math and returns a number, and show_total(total) that only prints. Call them together for [10, 20] with 10% tax. The logic function must contain no print at all — that is what makes it testable.
Write a mini app with clearly separated sections: data (get_students() returning a list of dicts), logic (top_student(students)), and display (show(student)). Wire them together in one line at the bottom. Each function should do exactly one job.
Code inside if __name__ == "__main__": runs only when the file is run directly, not when another file imports it — so your module can be a tool and a library. Write add(a, b), print __name__, and put a demo call inside the guard.
__main__
5
def add(a, b):
return a + b
print(__name__)
if __name__ == "__main__":
print(add(2, 3))
🧰
Task 9: Boss Level: A Reusable Toolbox
Boss
Design a temperature mini-module: c_to_f, f_to_c, and describe(celsius) returning "freezing" (≤0), "cold" (<15), "mild" (<25) or "hot". Every function must be pure — no printing. Then, under a __main__ guard, print a small demo table for −5, 10, 20 and 30 °C.