Module 4 Lesson 10: Modularizing OOP Projects
Organize your code like a professional. Learn how to split complex classes into different modules and use __init__.py for clean imports.
Module 4 Lesson 10: Modularizing OOP Projects
In Module 3, we learned how to import simple functions from separate files. In OOP, we take this a step further. Instead of having one massive classes.py file, we give every major class its own home. In this lesson, we’ll learn how to structure a professional-grade Python project.
Lesson Overview
In this lesson, we will cover:
- The Single-Class Rule: Why every class needs its own file.
- The
models/Folder: Organizing your object templates. - Cross-Module Imports: How classes in different files talk to each other.
- Avoiding "Circular Imports": The most common modularity bug.
1. The Single-Class Rule
In professional projects, we usually put one class per file. If you have a User class and an Admin class (which inherits from User), your folder might look like this:
my_project/
├── main.py
├── models/
│ ├── __init__.py
│ ├── user.py
│ └── admin.py
2. Setting Up the Files
File: models/user.py
class User:
def __init__(self, name):
self.name = name
File: models/admin.py
from models.user import User
class Admin(User):
def delete_user(self, user):
print(f"Admin deleting user: {user.name}")
3. The __init__.py File
Whenever you see a file named __init__.py in a folder, it tells Python: "Treat this folder as a Package." This allows you to import everything from that folder in one line.
File: main.py
from models.admin import Admin
from models.user import User
new_user = User("Alex")
super_user = Admin("TheBoss")
super_user.delete_user(new_user)
4. Avoiding Circular Imports
A circular import happens when user.py tries to import admin.py, while admin.py is simultaneously trying to import user.py.
- The Symptom: Your program crashes with an
ImportError. - The Fix: Keep your hierarchies simple. If two classes need to know too much about each other, they might actually belong in the same file!
Practice Exercise: The Game Engine Structure
- Create a folder named
my_game/. - Inside, create a
models/subfolder. - Create
models/entity.pywith a baseEntityclass. - Create
models/player.pywith aPlayerclass that inherits fromEntity. - Create a
main.pyin themy_game/folder that importsPlayerand prints their stats.
Quick Knowledge Check
- Why is it better to put each class in its own file?
- What is the purpose of the
__init__.pyfile? - What happens if Class A imports Class B, and Class B imports Class A?
- What is the standard folder name for storing class definitions?
Key Takeaways
- Modularization makes code easier to navigate.
- Packages (
folders with __init__.py) help group related classes. - Always be careful with file paths when importing across folders.
- Professional Python projects follow a "Models" and "Logic" separation.
What’s Next?
We’ve finished the lessons for Module 4! Now it’s time to apply everything—inheritance, encapsulation, and modularity—to build a RPG Character System in our Hands-on Projects!