🧠 Mental Model: Architectural Blueprints
The House Blueprint Metaphor
Think of a class like an architectural blueprint for a house. The blueprint defines what every house built from it will have (rooms, doors, windows), but it's not a house itself. When builders use the blueprint to construct actual houses, each house is an "object" - a real instance with specific features.
- 🏗️ Class - The blueprint (template) defining structure and behavior
- 🏠 Objects - Actual houses built from the blueprint (instances)
- 🔧 Methods - Actions the house can perform (turn on lights, lock doors)
- 📋 Attributes - Properties of each house (color, size, address)
📋 Class Blueprint
class House:
def __init__(self, color, size):
self.color = color
self.size = size
self.lights_on = False
def turn_on_lights(self):
self.lights_on = True
🏠 Object Instances
🏗️ Classes: Creating Your Own Data Types
A class is a template that defines the structure and behavior for objects. It's like creating your own custom data type with specific properties and actions. Classes help organize related data and functions together.
Creating Your First Class
class Student:
"""A class to represent a student."""
def __init__(self, name, age, grade):
"""Initialize a new student (the constructor)."""
self.name = name # Instance attribute
self.age = age # Instance attribute
self.grade = grade # Instance attribute
self.courses = [] # Start with empty course list
def add_course(self, course):
"""Add a course to the student's schedule."""
self.courses.append(course)
print(f"{self.name} enrolled in {course}")
def get_info(self):
"""Return formatted student information."""
return f"{self.name}, age {self.age}, grade {self.grade}"
# Creating objects (instances) from the class
student1 = Student("Alice", 16, 10)
student2 = Student("Bob", 17, 11)
# Using methods on objects
print(student1.get_info()) # Alice, age 16, grade 10
student1.add_course("Math") # Alice enrolled in Math
🎮 Interactive Class Builder
Create your own student and see OOP in action:
🔧 The __init__ Method: Object Constructor
The __init__ method is special - it's automatically called when you create a new object. Think of it as the "setup instructions" that run when a house is built from the blueprint, setting up the initial state.
✅ Constructor in Action
class Car:
def __init__(self, make, model, year):
# These run automatically!
self.make = make
self.model = model
self.year = year
self.mileage = 0 # Default value
# Creating objects calls __init__
my_car = Car("Toyota", "Camry", 2020)
🔍 What Happens
- Python creates new object
- Calls
__init__
automatically - Sets up instance attributes
- Returns ready-to-use object
🧠 The 'self' Parameter
self refers to the specific object being created or used. It's like saying "this particular house" when multiple houses exist. Python automatically passes the object as the first argument to all methods.
⚙️ Methods: What Objects Can Do
Methods are functions that belong to a class. They define what actions objects can perform. Think of them as the "abilities" or "behaviors" that every house built from the blueprint can do.
Bank Account Example
class BankAccount:
def __init__(self, owner, initial_balance=0):
self.owner = owner
self.balance = initial_balance
self.transaction_history = []
def deposit(self, amount):
"""Add money to the account."""
if amount > 0:
self.balance += amount
self.transaction_history.append(f"Deposited ${amount}")
return f"Deposited ${amount}. New balance: ${self.balance}"
return "Invalid amount"
def withdraw(self, amount):
"""Remove money from the account."""
if amount > 0 and amount <= self.balance:
self.balance -= amount
self.transaction_history.append(f"Withdrew ${amount}")
return f"Withdrew ${amount}. New balance: ${self.balance}"
return "Insufficient funds or invalid amount"
def get_balance(self):
"""Return current balance."""
return f"{self.owner}'s balance: ${self.balance}"
# Using the BankAccount class
account = BankAccount("Alice", 100)
print(account.deposit(50)) # Deposited $50. New balance: $150
print(account.withdraw(30)) # Withdrew $30. New balance: $120
print(account.get_balance()) # Alice's balance: $120
🎮 Try the Bank Account
⚠️ Critical Pitfall: Mutable Default Arguments
Dangerous Assumption: Default Lists Are Safe
Beginner trap: Using mutable objects (like lists) as default arguments creates shared state between all instances! All objects will share the same list, leading to unexpected behavior.
❌ Wrong: Mutable Default
class Student:
def __init__(self, name, courses=[]): # DANGER!
self.name = name
self.courses = courses # All students share same list!
alice = Student("Alice")
bob = Student("Bob")
alice.courses.append("Math")
print(bob.courses) # ['Math'] - Bob has Alice's course!
✅ Correct: None Default
class Student:
def __init__(self, name, courses=None):
self.name = name
self.courses = courses if courses else [] # Safe!
alice = Student("Alice")
bob = Student("Bob")
alice.courses.append("Math")
print(bob.courses) # [] - Bob has his own empty list
🧠 Safe Default Pattern
Always use None as the default for mutable arguments, then create a new object inside the method. This ensures each instance gets its own separate copy.
🎯 Mastery Check: OOP Basics Understanding
Question 1: Classes vs Objects
What is the relationship between a class and an object?
A class is a blueprint/template, an object is an instance created from that class
Classes and objects are the same thing
Objects are blueprints for creating classes
Question 2: The __init__ Method
When is the __init__ method called?
Automatically when a new object is created from the class
Only when you explicitly call it with object.__init__()
When the program starts running
Question 3: Mutable Default Arguments
Why should you avoid using a list as a default parameter in __init__?
All instances would share the same list object, causing unexpected behavior
Lists are not allowed in __init__ methods
It makes the code run slower
🎯 Ready for Advanced OOP!
What You've Mastered
- ✅ Classes as blueprints and objects as instances
- ✅ The __init__ constructor method and self parameter
- ✅ Instance attributes and methods
- ✅ Creating and using objects
- ✅ Critical pitfall of mutable default arguments
Now that you understand the basics of classes and objects, let's explore inheritance, polymorphism, and other advanced OOP concepts!
Continue to Advanced OOP →