Modules
A Python module is any .py file. Organising code into modules makes it reusable, testable, and maintainable. The standard library provides an enormous amount of ready-to-use functionality.
# Importing the whole module:
import math
import random
import os
print(math.pi) # 3.141592653589793
print(math.sqrt(25)) # 5.0
print(math.floor(4.7)) # 4
print(random.randint(1, 100))
print(os.getcwd()) # current working directory
# Import specific names (from module import name):
from math import pi, sqrt, floor
from datetime import date, timedelta
from pathlib import Path
print(sqrt(16)) # 4.0 — no math. prefix
print(date.today()) # 2025-04-01
deadline = date.today() + timedelta(days=30)
print(f"Deadline: {deadline}")
print(Path.cwd()) # current directory as Path object
Creating Your Own Module
# grading.py — save as a separate file
VAT_RATE = 0.15
def grade_label(mark):
"""Return grade label for a numeric mark."""
if mark >= 80: return "Distinction"
if mark >= 70: return "Merit — Upper"
if mark >= 60: return "Merit"
if mark >= 50: return "Pass"
return "Not yet competent"
def class_stats(marks):
"""Return dict with mean, min, max, pass_rate."""
n = len(marks)
if n == 0:
return {}
passed = sum(1 for m in marks if m >= 50)
return {
"mean": sum(marks) / n,
"min": min(marks),
"max": max(marks),
"pass_rate": passed / n
}
# Guards against running when imported:
if __name__ == "__main__":
print("Testing grading module...")
print(grade_label(74))
print(class_stats([65, 72, 80, 58, 91]))
# main.py — in the same directory
from grading import grade_label, class_stats, VAT_RATE
marks = [65, 72, 80, 58, 91, 44, 77]
for mark in marks:
print(f"{mark}%: {grade_label(mark)}")
stats = class_stats(marks)
print(f"Mean: {stats['mean']:.1f}%")
print(f"Pass rate: {stats['pass_rate']:.0%}")
The __name__ == "__main__" Guard
When Python runs a file directly, it sets __name__ to "__main__". When a file is imported as a module, __name__ is the module name. The guard prevents test code from running when the module is imported.
Practice Task
Your Turn
Create a stats.py module with: average(marks), median(marks), std_dev(marks), percentile(marks, p) returning the p-th percentile. Add the __name__ guard with tests. Import and use all four functions in a main script with a list of 10 marks.
Common Mistakes
- Circular imports — A imports B, B imports A. Restructure your code.
- Naming your file the same as a standard library module (e.g.
math.py) — your file shadows the standard library. from module import *pollutes the namespace — avoid it.- Forgetting
__name__ == "__main__"guard — test code runs every time the module is imported.
Professional Tip
The standard library covers 80% of common needs — before installing a package, check if Python has built-in support. The docs at docs.python.org are comprehensive and well-written.
Mini Quiz
What does the if __name__ == '__main__' guard do?