Free Study Material

Python Modules

Introduction

Every program in this unit so far has used only Python's own built-in functions. A module is a file of pre-written Python code you can bring into your own program — this topic covers how to actually bring one in.

Concept

A module is a file containing ready-made functions and values, grouped around a common purpose (the next three topics cover three specific ones: math, random, statistics). Python offers several ways to bring a module's contents into your program:

  • import module_name — brings in the whole module; its contents are used as module_name.function_name(...).
  • import module_name as alias — same as above, but under a shorter name of your choosing.
  • from module_name import function_name — brings in one specific function directly, used on its own, with no module prefix at all.
  • from module_name import \* — brings in everything from the module directly, with no prefix.

Worked Example

import math
print(math.sqrt(25))

import statistics as stats
print(stats.mean([10, 20, 30]))

from math import factorial
print(factorial(5))

import math brings in the whole math module, so its sqrt() function is called as math.sqrt(25), giving 5.0. import statistics as stats brings in the whole statistics module under the shorter name stats, so mean() is called as stats.mean([10, 20, 30]), giving 20. from math import factorial brings in only factorial directly — it's then called on its own, factorial(5), without needing math. in front, giving 120.

Warning: from module import * brings in everything with no prefix at all, which can silently overwrite one of your own variables or functions if it happens to share a name with something inside the module — importing only the specific names you actually need (from module import name) avoids this risk entirely.

Explanation

import module_name (with the prefix) is the safest default specifically because the prefix makes it immediately clear, everywhere in your code, exactly which module a function came from — this becomes genuinely important once a program imports more than one module.

Summary

A module is a file of ready-made code, brought in with import module_name (prefixed access), import module_name as alias (a shorter prefix), from module_name import name (direct access to one specific name), or from module_name import * (direct access to everything — riskier, since it can silently clash with your own names).

Definition

A Module is simply a Python file (.py) containing variables, functions, and classes that you can include in your program.

Why use Modules?

  • Reusability: Write code once, use it everywhere.
  • Organization: Keep your main program clean by moving complex logic to separate files.
  • Efficiency: Use optimized code written by experts (like the `math` module).

Syntax Comparison

Style Code How to Use
Standard import math math.pi
Specific from math import pi pi
Alias import math as m m.pi
# Style 1: Full Import (Safest)
import math
print("Value of Pi (Style 1):", math.pi)

# Style 2: Specific Import (Cleanest)
from math import sqrt
print("Square root of 25:", sqrt(25))

# Style 3: Alias (Laziest/Fastest)
import math as m
print("Factorial of 5:", m.factorial(5))

Introduction

The math module is the most commonly used module in this course — it provides mathematical functions and constants that Python's built-in operators alone don't cover.

Concept

  • sqrt(x) — square root of x.
  • pow(x, y) — x raised to the power y (like x ** y, but as a module function).
  • ceil(x) — rounds x up to the nearest whole number.
  • floor(x) — rounds x down to the nearest whole number.
  • factorial(x) — the factorial of x (x!).
  • pi — the constant π (3.14159...), used as a value, not called with ().

Worked Example

import math

print(math.sqrt(49))
print(math.pow(2, 5))
print(math.ceil(4.2))
print(math.floor(4.8))
print(math.factorial(4))
print(math.pi)

math.sqrt(49) gives 7.0. math.pow(2, 5) gives 32.0 — note that pow() always returns a float, unlike the * operator, which returns an int when both of its inputs are integers. math.ceil(4.2) rounds up to 5; math.floor(4.8) rounds down to 4 — notice both move 4.2 and 4.8 towards different* whole numbers, since one always rounds up and the other always rounds down, regardless of which whole number is actually closer. math.factorial(4) gives 24 (4 × 3 × 2 × 1). math.pi prints 3.141592653589793 — Python's closest possible float approximation of π, used directly as a constant, with no () needed since it isn't a function.

Note: math.pow(2, 5) always returns a float (32.0); the built-in operator, 2 5, returns an int (32) when both operands are integers. Both compute the same value, but their result types differ.

Explanation

ceil() and floor() are easy to mix up because both are "rounding" functions, but they always move in one fixed direction each, regardless of how close the value already is to a whole number — ceil() always rounds up, even for 4.01; floor() always rounds down, even for 4.99. Neither one rounds to the nearest whole number the way everyday rounding does.

Summary

The math module provides sqrt(), pow() (always returns a float), ceil() (always rounds up), floor() (always rounds down), factorial(), and the constant pi — every function needs the math. prefix unless imported directly with from math import name.

Constants

  • math.pi: Returns the value of π (3.14159...). Used for circle calculations.
  • math.e: Returns the value of Euler’s number (2.71828...). Used in exponential growth/decay.
import math
print("Value of Pi:", math.pi)
print("Area of circle (r=5):", math.pi * 5 * 5) # 78.539...

Comparison: Ceiling vs Floor

math.ceil(x)

Rounds UP to the nearest integer.
Think: "Ceiling" is above you.

ceil(4.1) → 5
math.floor(x)

Rounds DOWN to the nearest integer.
Think: "Floor" is below you.

floor(4.9) → 4
# Rounding Examples
x = 5.9
y = 5.1

print("Floor of 5.9:", math.floor(x)) # Output: 5
print("Ceil of 5.1:",  math.ceil(y))  # Output: 6

# Note: For negative numbers, 'down' means more negative!
print("Floor of -3.2:", math.floor(-3.2)) # Output: -4

Function Definitions

  • math.pow(x, y): Returns x raised to the power of y ($x^y$). Note that unlike the ** operator, this always returns a float.
  • math.sqrt(x): Returns the square root of x ($\sqrt{x}$).
  • math.fabs(x): Returns the absolute value (removes the negative sign). Always returns a float.
# Power and Roots
print(math.pow(2, 3))   # 8.0 (Float)
print(math.sqrt(49))    # 7.0

# Absolute Value
print(math.fabs(-10))   # 10.0
print(math.fabs(10))    # 10.0

⚠️ CRITICAL WARNING: Use Radians!

Python's trig functions DO NOT accept Degrees (like 90° or 180°).
They expect the angle in RADIANS.

# Step 1: Convert Degrees to Radians
rad = math.radians(degrees)

# Step 2: Use the trig function
val = math.sin(rad)
# Trigonometry Example: Calculate Sin(30)
# We know Sin(30 degrees) should be 0.5

# Wrong Way
print(math.sin(30)) # Output: -0.988... (Incorrect!)

# Correct Way
angle_in_degrees = 30
angle_in_radians = math.radians(angle_in_degrees)

print(math.sin(angle_in_radians)) # Output: 0.4999... (Correct)

Introduction

Every value in every program so far has been completely predictable — the same code always produces the same result. The random module breaks that deliberately, generating unpredictable values on purpose.

Concept

  • random.random() — a random float, 0.0 up to (but never including) 1.0.
  • random.randint(a, b) — a random whole number between a and b, both included.
  • random.randrange(start, stop) — a random whole number from start up to (not including) stop, following the exact same "stop excluded" rule as range().
  • random.choice(sequence) — a random single element picked from a list, tuple, or string.

Every one of these genuinely returns a different value on different runs — there is no fixed, single correct output to check against.

Worked Example

import random

dice_roll = random.randint(1, 6)
print("Dice roll:", dice_roll)
print(1 <= dice_roll <= 6)

fruits = ["apple", "banana", "mango", "grape"]
picked = random.choice(fruits)
print("Picked:", picked)
print(picked in fruits)

random.randint(1, 6) returns a whole number from 1 to 6, inclusive — a different value on each run, but always somewhere in that exact range, which is exactly what 1 <= dice_roll <= 6 confirms by printing True every single time, regardless of which specific number was rolled. random.choice(fruits) picks one element from fruits — again different each run, but always genuinely one of the four fruits, which picked in fruits confirms the same way, always printing True.

Note: This program's exact printed values (the dice number, the fruit name) change every time you run it — that's the module working correctly, not a bug. What stays fixed and checkable is the range the value falls in, which is exactly what this worked example checks instead of a specific number.

Explanation

Because random's output genuinely changes every run, a program using it needs a different way to confirm it's working correctly than tracing a specific expected value — checking that the result always satisfies a known condition (like 1 <= dice_roll <= 6) is that alternative, and it's exactly how this module's own examples above are verified.

Summary

random.random() gives a random float below 1.0; random.randint(a, b) gives a random whole number including both ends; random.randrange(start, stop) excludes stop, like range(); random.choice(sequence) picks one random element. All four genuinely vary between runs by design — a program using them is checked by confirming the result satisfies a known condition, not by tracing one fixed expected value.

Concept: Pseudo-Randomness

Since computers are logical, they cannot be truly random (like rolling a physical die).

Python uses a Seed Number (usually based on the current time) and runs it through a complex mathematical formula to produce a stream of numbers that appears random.

Syntax: random.random()

  • Return Type: Float
  • Range: 0.0 <= N < 1.0
  • Rule: It includes 0.0 but NEVER returns 1.0.
import random

# Generate a random float
val = random.random()
print("Random Float:", val) 
# Output: 0.732... (Changes every time)

# Trick: Scaling it to 0-100 (e.g., for a percentage chance)
print("Percentage:", val * 100)

Syntax: random.randint(a, b)

Returns a random integer N such that a <= N <= b.

# Example: Rolling a Dice
dice = random.randint(1, 6)

⚠️ CRITICAL NOTE: Unlike standard Python ranges, this function INCLUDES the endpoint 'b'.

# Rolling a standard dice
roll = random.randint(1, 6)
print("You rolled a:", roll) 
# Possible Outputs: 1, 2, 3, 4, 5, 6

Syntax: random.randrange()

  • Structure: randrange(start, stop, step)
  • Rule: The 'stop' value is EXCLUDED (just like normal range).
Case A: randrange(10)
Picks from 0 to 9.
(10 is excluded)
Case B: randrange(0, 10, 2)
Picks from [0, 2, 4, 6, 8].
(Only even numbers)
# Pick a random even number less than 10
num = random.randrange(0, 10, 2)
print("Random Even Number:", num)
# Possible Outputs: 0, 2, 4, 6, 8 (Never 10!)

The "Endpoint" Trap

Function Code Range Interval Includes Endpoint?
randint randint(1, 10) [1, 10] YES
randrange randrange(1, 10) [1, 10) NO

Introduction

You've already summarised a list using min(), max(), and sum(). The statistics module goes further, providing the standard statistical measures CBSE expects by name.

Concept

  • mean(data) — the average of all values.
  • median(data) — the middle value, once data is sorted (the average of the two middle values, if there's an even count).
  • mode(data) — the most frequently occurring value.
  • stdev(data) — the standard deviation, a measure of how spread out the values are from the mean.

data can be a list or a tuple of numbers.

Worked Example

import statistics

marks = [67, 85, 92, 67, 74]

print(statistics.mean(marks))
print(statistics.median(marks))
print(statistics.mode(marks))

statistics.mean(marks) adds all five values (67 + 85 + 92 + 67 + 74 = 385) and divides by 5, giving 77. statistics.median(marks) first sorts the data ([67, 67, 74, 85, 92]) and takes the middle value — the third of five — giving 74. statistics.mode(marks) returns 67, since it's the only value that occurs more than once (twice, while every other value occurs just once).

Warning: statistics.mode() raises a StatisticsError if every value in the data occurs exactly the same number of times — there's no single "most common" value to return. mode() is only safe to call when at least one value is known to repeat more often than the rest.

Explanation

median()'s definition depends on sorted order, not the order data was originally given in — statistics.median() sorts internally before picking the middle value, so the caller never needs to sort the data first, unlike a hand-written median calculation that would need that step done explicitly.

Summary

The statistics module provides mean() (average), median() (the middle value once sorted), mode() (the most frequent value), and stdev() (spread from the mean) — all built specifically for statistical summaries, complementing the more general min()/max()/sum() already used with lists and tuples.

Comparison Table

Function Definition Example: [1, 2, 2, 10]
mean() Average (1+2+2+10) / 4 = 3.75
median() Middle Value Sorted: 1, 2, 2, 10
Result: 2
mode() Most Common '2' appears twice.
Result: 2
import statistics

data = [10, 20, 30, 40]
avg = statistics.mean(data)

print("Average:", avg) 
# Output: 25.0
# Case 1: Odd number of items
scores_1 = [1, 5, 9]
print("Median 1:", statistics.median(scores_1)) 
# Output: 5

# Case 2: Even number of items (Middle are 5 and 7)
scores_2 = [1, 5, 7, 100]
print("Median 2:", statistics.median(scores_2)) 
# Output: 6.0 (Average of 5 and 7)

Warning: Multiple Modes

What if there is a tie? (e.g., [1, 1, 2, 2])?

  • Older Python (< 3.8): Raises a StatisticsError.
  • Newer Python (3.8+): Returns the first mode encountered.
  • Exam Tip: Usually, exam questions provide clear data with a single mode.
votes = ["Red", "Blue", "Red", "Green", "Red"]
winner = statistics.mode(votes)

print("Winner:", winner)
# Output: 'Red'

Introduction

A working recap of this chapter — importing a module, and using one function from each of the three modules covered — closing out this unit's very last topic.

Concept

  • Import: import module_name (prefixed access) or from module_name import name (direct access to one name).
  • math: sqrt(), pow(), ceil(), floor(), factorial(), the constant pi.
  • random: random(), randint(a, b), randrange(start, stop), choice(sequence) — genuinely different results each run.
  • statistics: mean(), median(), mode(), stdev().

Worked Example

import math
import random
import statistics

marks = [78, 85, 92, 67, 74]

print("Average marks:", statistics.mean(marks))
print("Square root of highest mark:", math.sqrt(max(marks)))

topper_index = random.randint(0, len(marks) - 1)
print("Randomly selected mark:", marks[topper_index])
print("Is a valid mark from the list:", marks[topper_index] in marks)

statistics.mean(marks) gives 79.2 — the same total-then-divide calculation, this time computed by the module instead of by hand. math.sqrt(max(marks)) combines a built-in function (max()) with a module function (math.sqrt()) in a single line — max(marks) is 92, so this prints math.sqrt(92)'s result. random.randint(0, len(marks) - 1) generates a valid index for marks (from 0 to 4, since len(marks) - 1 is 4) — a different index each run, but marks[topper_index] in marks still always prints True, since whatever index is picked genuinely comes from that list.

Tip: random.randint(0, len(marks) - 1) is the standard pattern for picking a valid random position in any list — len(marks) - 1 is always the list's last valid index, exactly as covered when list indexing was first introduced.

Explanation

This closing example deliberately combines all three modules with material from earlier chapters — max() on a list, an index expression, membership with in — because that's exactly how modules are actually used in practice: alongside everything else already learned, not in isolation.

Summary

A module is brought in with import or from ... import; math provides numeric functions and the constant pi; random generates unpredictable values within a known range; statistics provides mean(), median(), mode(), and stdev() — closing out this unit's full progression from Python's basic syntax through control flow, loops, strings, and all three collection types.

What is a Module?

A Module is a file containing pre-written code (functions and variables) that you can re-use. Think of Python as an empty desk, and a Module as a Toolbox. You must open (Import) the toolbox before you can use the hammer inside.

Style Code Usage Example Best For...
Standard import math math.sqrt(4) Safety (No name clashes)
Specific from math import sqrt sqrt(4) Convenience (Less typing)
Alias import math as m m.sqrt(4) Speed (Short nickname)

Module 1: Math

Rule: Standard mathematical operations.
Import: import math

Function Description Example Input → Output
math.ceil(x) Rounds UP to nearest integer 4.1 → 5
math.floor(x) Rounds DOWN to nearest integer 4.9 → 4
math.pow(x,y) Returns $x^y$ as a Float 2, 3 → 8.0
math.sqrt(x) Square root ($\sqrt{x}$) 49 → 7.0
math.fabs(x) Absolute Value (Positive) -10 → 10.0
math.sin(x) Sine of angle (Must be Radians) radians(30) → 0.5
Constants math.pi, math.e 3.14159...

Want the full course?

Unlock all chapters, video lectures, and SQL practice exercises.

Get Full Access