- What are user-defined modules — creating your own .py files
- Why create modules — reusability and organization
- Creating modules — step-by-step guide
- Importing modules — using your custom modules
- Module structure — best practices and patterns
- Testing modules — using if __name__ == "__main__"
What is a User-Defined Module?
A user-defined module is simply a Python file (.py) that you create yourself. It contains functions, classes, and variables that you want to reuse across multiple programs. Think of it as your personal toolbox — you build it once and use it everywhere.
Just like how Python comes with built-in modules like math and datetime, you can create your own modules to organize your code. This is the foundation of writing clean, professional Python code.
💡 Key concept: Any .py file you create can be imported as a module. This means you can write code once, save it, and import it into any other Python program. It's like creating your own personal library!
Why Create Your Own Modules?
Benefits of Creating Modules
# Without modules (repetitive code in every file)
# File 1: project1.py
def calculate_area(length, width):
return length * width
def calculate_perimeter(length, width):
return 2 * (length + width)
# File 2: project2.py
def calculate_area(length, width):
return length * width
def calculate_perimeter(length, width):
return 2 * (length + width)
# File 3: project3.py
def calculate_area(length, width):
return length * width
def calculate_perimeter(length, width):
return 2 * (length + width)
# ❌ This is repetitive and hard to maintain!
# With modules (write once, use everywhere)
# Save this as: geometry.py
def calculate_area(length, width):
"""Calculate the area of a rectangle"""
return length * width
def calculate_perimeter(length, width):
"""Calculate the perimeter of a rectangle"""
return 2 * (length + width)
def calculate_circle_area(radius):
"""Calculate the area of a circle"""
import math
return math.pi * radius ** 2
# Now in any other file:
import geometry
area = geometry.calculate_area(5, 3)
perimeter = geometry.calculate_perimeter(5, 3)
circle_area = geometry.calculate_circle_area(4)
print(f"Area: {area}") # 15
print(f"Perimeter: {perimeter}") # 16
print(f"Circle area: {circle_area:.2f}") # 50.27
# ✅ Benefits:
# 1. Write once — use many times
# 2. Easy to update — fix in one place
# 3. Organized code — related functions grouped together
# 4. Reusable across projects
# 5. Shareable with others
Benefits of user-defined modules:
- Reusability — write code once, use it everywhere
- Maintainability — update code in one place
- Organization — group related functions together
- Shareability — share modules with others
- Collaboration — team members can work on different modules
Quick Check: What is the main benefit of creating your own modules? (Answer: Code reusability and organization)
Creating Your First Module
Step-by-Step Module Creation
# Step 1: Create a new Python file
# Name it: my_utils.py
# Step 2: Write your functions and variables
# my_utils.py
"""Utility functions for everyday programming"""
# Constants
MAX_RETRIES = 3
TIMEOUT = 30
# Functions
def greet(name, greeting="Hello"):
"""Greet a person with a custom greeting"""
return f"{greeting}, {name}!"
def add_numbers(a, b):
"""Add two numbers"""
return a + b
def subtract_numbers(a, b):
"""Subtract two numbers"""
return a - b
def multiply_numbers(a, b):
"""Multiply two numbers"""
return a * b
def divide_numbers(a, b):
"""Divide two numbers"""
if b == 0:
raise ValueError("Cannot divide by zero")
return a / b
def is_even(number):
"""Check if a number is even"""
return number % 2 == 0
def get_average(numbers):
"""Calculate the average of a list of numbers"""
if not numbers:
return None
return sum(numbers) / len(numbers)
# Step 3: Save the file as my_utils.py
# Step 4: Now you can import it in any other Python file!
# Step 5: Use your module
import my_utils
print(my_utils.greet("Alice")) # Hello, Alice!
print(my_utils.add_numbers(5, 3)) # 8
print(my_utils.is_even(4)) # True
# Step 6: Import specific functions
from my_utils import greet, is_even
print(greet("Bob", "Hi")) # Hi, Bob!
print(is_even(7)) # False
Creating a module is easy:
- Step 1 — Create a .py file
- Step 2 — Add your code (functions, classes, variables)
- Step 3 — Add docstrings for documentation
- Step 4 — Save the file
- Step 5 — Import and use it anywhere!
Quick Check: What file extension do Python modules use? (Answer: .py)
Importing User-Defined Modules
Different Ways to Import
# Assuming we have a module named: my_utils.py
# 1. Import the entire module
import my_utils
# Access using dot notation
print(my_utils.greet("Alice"))
print(my_utils.add_numbers(5, 3))
# 2. Import specific functions
from my_utils import greet, add_numbers
# Use directly without module prefix
print(greet("Bob"))
print(add_numbers(10, 5))
# 3. Import with an alias
import my_utils as utils
print(utils.greet("Charlie"))
print(utils.divide_numbers(10, 2))
# 4. Import all functions (not recommended)
from my_utils import *
print(greet("David"))
print(is_even(6))
# 5. Import multiple functions
from my_utils import greet, is_even, get_average
print(greet("Eve"))
print(is_even(9))
print(get_average([1, 2, 3, 4, 5]))
# 6. Import and rename functions
from my_utils import greet as say_hello
print(say_hello("Frank"))
# 7. Import from a package
# from my_package import module1
# 8. Dynamic import
import importlib
my_utils = importlib.import_module('my_utils')
print(my_utils.greet("Grace"))
Import methods summary:
- import module — import everything, use with prefix
- from module import item — import specific items
- import module as alias — import with a shorter name
- from module import * — import all (avoid this)
- from module import item as alias — import with custom name
Quick Check: What is the recommended way to import a module? (Answer: import module or from module import specific_function)
Module Structure and Best Practices
Writing Professional Modules
# Professional module structure
# ====================================================
# Module: my_utils.py
# Description: Utility functions for data processing
# Author: Your Name
# Created: 2026-08-02
# ====================================================
# 1. Module docstring (explains what the module does)
"""
Utility functions for everyday data processing tasks.
This module provides common functions for:
- Mathematical operations
- String manipulation
- Data validation
- File handling utilities
"""
# 2. Imports (at the top)
import math
import datetime
from typing import List, Optional
# 3. Constants (UPPERCASE)
MAX_FILE_SIZE = 1024 * 1024 # 1MB
DEFAULT_ENCODING = "utf-8"
API_TIMEOUT = 30
# 4. Functions (with docstrings and type hints)
def validate_email(email: str) -> bool:
"""
Validate an email address format.
Args:
email (str): Email address to validate
Returns:
bool: True if valid, False otherwise
Example:
>>> validate_email("user@example.com")
True
>>> validate_email("invalid-email")
False
"""
return "@" in email and "." in email
def format_currency(amount: float, currency: str = "$") -> str:
"""
Format a number as currency.
Args:
amount (float): The amount to format
currency (str): Currency symbol (default: $)
Returns:
str: Formatted currency string
Example:
>>> format_currency(1234.56)
'$1,234.56'
"""
return f"{currency}{amount:,.2f}"
def calculate_age(birth_date: datetime.date) -> int:
"""
Calculate age from birth date.
Args:
birth_date (datetime.date): Date of birth
Returns:
int: Age in years
"""
today = datetime.date.today()
age = today.year - birth_date.year
if (today.month, today.day) < (birth_date.month, birth_date.day):
age -= 1
return age
# 5. Classes
class DataProcessor:
"""Process and transform data"""
def __init__(self, data: List):
self.data = data
def clean(self) -> List:
"""Clean the data"""
return [item.strip() for item in self.data if item]
def transform(self, func):
"""Apply a transformation function"""
return [func(item) for item in self.data]
# 6. Main guard (for testing)
if __name__ == "__main__":
# This code only runs when this file is executed directly
print("Testing my_utils module...")
# Test email validation
print(f"Email 'test@email.com': {validate_email('test@email.com')}")
print(f"Email 'invalid': {validate_email('invalid')}")
# Test currency formatting
print(f"Format 1234.56: {format_currency(1234.56)}")
# Test age calculation
birth = datetime.date(2000, 1, 1)
print(f"Age: {calculate_age(birth)} years")
Professional module structure:
- Module docstring — explains what the module does
- Imports at top — keep all imports at the beginning
- Constants in UPPERCASE — easy to identify
- Function docstrings — describe each function
- Type hints — specify parameter and return types
- Main guard — for testing when run directly
Quick Check: What is the purpose of if __name__ == "__main__"? (Answer: To run code only when the module is executed directly, not when imported)
Using Variables and Functions
Working with Module Members
# Complete example: calculator.py
# calculator.py
"""Simple calculator module with basic operations"""
# Module-level variables
VERSION = "1.0.0"
AUTHOR = "Python Learner"
# Functions
def add(*args):
"""Add any number of numbers"""
return sum(args)
def subtract(a, b):
"""Subtract b from a"""
return a - b
def multiply(*args):
"""Multiply any number of numbers"""
result = 1
for num in args:
result *= num
return result
def divide(a, b):
"""Divide a by b"""
if b == 0:
raise ValueError("Division by zero is not allowed")
return a / b
def power(base, exponent):
"""Calculate base raised to exponent"""
return base ** exponent
def sqrt(number):
"""Calculate square root"""
if number < 0:
raise ValueError("Cannot calculate square root of negative number")
return number ** 0.5
# A class
class Calculator:
"""A calculator class with memory"""
def __init__(self):
self.memory = 0
def add_to_memory(self, value):
self.memory += value
return self.memory
def clear_memory(self):
self.memory = 0
return self.memory
def get_memory(self):
return self.memory
# Using the calculator module:
# import calculator
# print(calculator.add(1, 2, 3, 4)) # 10
# print(calculator.multiply(2, 3, 4)) # 24
# print(calculator.VERSION) # 1.0.0
# calc = calculator.Calculator()
# calc.add_to_memory(5)
# calc.add_to_memory(10)
# print(calc.get_memory()) # 15
Module members:
- Variables — constants and configuration
- Functions — reusable operations
- Classes — create objects with methods
- Modules — can be imported as a whole
Quick Check: Can a module contain both functions and classes? (Answer: Yes, modules can contain any Python code)
Testing Your Modules
Using the Main Guard
# Using if __name__ == "__main__" for testing
# my_module.py
def add(a, b):
return a + b
def multiply(a, b):
return a * b
def subtract(a, b):
return a - b
# Testing code - only runs when executed directly
if __name__ == "__main__":
print("Running tests...")
# Test add
assert add(2, 3) == 5, "Add function failed"
print("✅ add() test passed")
# Test multiply
assert multiply(4, 5) == 20, "Multiply function failed"
print("✅ multiply() test passed")
# Test subtract
assert subtract(10, 3) == 7, "Subtract function failed"
print("✅ subtract() test passed")
print("All tests passed! 🎉")
# When you run this file directly:
# $ python my_module.py
# Running tests...
# ✅ add() test passed
# ✅ multiply() test passed
# ✅ subtract() test passed
# All tests passed! 🎉
# When you import it:
# import my_module
# The tests won't run automatically
# You can still use the functions
# Advanced testing with multiple test cases
def run_tests():
"""Run all tests for the module"""
test_cases = [
(add, (2, 3), 5),
(add, (-1, 1), 0),
(add, (0, 0), 0),
(multiply, (2, 3), 6),
(multiply, (-2, 3), -6),
(multiply, (0, 5), 0),
(subtract, (5, 3), 2),
(subtract, (3, 5), -2),
(subtract, (0, 0), 0),
]
all_passed = True
for func, args, expected in test_cases:
result = func(*args)
if result != expected:
print(f"❌ {func.__name__}{args} returned {result}, expected {expected}")
all_passed = False
else:
print(f"✅ {func.__name__}{args} = {result}")
if all_passed:
print("🎉 All tests passed!")
else:
print("❌ Some tests failed")
if __name__ == "__main__":
run_tests()
Testing key points:
- if __name__ == "__main__" — runs only when executed directly
- assert statements — check that code works correctly
- Test functions — organize tests in functions
- Multiple test cases — test edge cases
- Clear output — show which tests passed or failed
Quick Check: Why do we use if __name__ == "__main__"? (Answer: To run test code only when the module is executed directly)
Try It Yourself
Experiment with creating and using user-defined modules in the editor below.
USER-DEFINED MODULES PRACTICE
========================================
1. CREATING A MODULE
2. USING THE MODULE
5 + 3 = 8
10 - 4 = 6
6 * 7 = 42
15 / 3 = 5.0
3. CONSTANTS IN MODULES
PI: 3.14159
E: 2.71828
4. USING IF __NAME__ == '__MAIN__'
Testing math functions...
All tests passed!
User-defined modules practice complete!
You've Got It!
You now know how to create and use user-defined modules in Python. You understand the importance of code organization, reusability, and proper module structure.
Quick Quiz
Test what you've learned:
Frequently Asked Questions
How do I create a user-defined module?
import filename.
What is the difference between importing and executing a module?
__name__ variable changes to help distinguish between the two.
Why should I avoid using "from module import *"?
from module import * pollutes your namespace by importing all names from the module. This can cause conflicts if two modules have the same function name and makes your code harder to understand and debug.
What's a common interview question about user-defined modules?
Can I use a user-defined module in multiple projects?
What is a package and how is it different from a module?
__init__.py file. Packages help organize related modules into a hierarchical structure.
Where to Go From Here
Now that you can create your own modules, check out these related topics:
📝 Assignments
Practice what you've learned with assignments.
Learn More →Python Packages
Learn how to organize modules into packages.
Learn More →File Handling
Learn how to work with files in Python.
Learn More →