Basics of Classes
Before diving into advanced OOP concepts, let’s start with the fundamentals: understanding what classes are and how to write them in Python.
What is a Class?
Section titled “What is a Class?”A class is a blueprint or template for creating objects. It defines:
- Attributes (data/variables)
- Methods (functions that operate on the data)
An object (or instance) is a specific realization of a class - a concrete example created from the blueprint.
Real-World Analogy
Section titled “Real-World Analogy”Think of a class like a cookie cutter:
- The class is the cookie cutter (the template)
- The objects are the cookies (specific instances created from the template)
All cookies made from the same cutter have the same shape, but each cookie is a separate object.
Basic Class Structure
Section titled “Basic Class Structure”Here’s the simplest class definition:
class Dog: pass # Empty class
# Create an instance (object)my_dog = Dog()print(type(my_dog)) # <class '__main__.Dog'><class '__main__.Dog'>The __init__ Method
Section titled “The __init__ Method”The __init__ method is a special method called a constructor. It’s automatically called when you create a new instance of a class.
class Dog: def __init__(self, name: str, breed: str): """Constructor - called when creating a new Dog instance""" self.name = name self.breed = breed
# Create instancesdog1 = Dog("Buddy", "Golden Retriever")dog2 = Dog("Max", "German Shepherd")
print(dog1.name) # "Buddy"print(dog2.breed) # "German Shepherd"BuddyGerman ShepherdUnderstanding self
Section titled “Understanding self”self refers to the current instance of the class. It’s the first parameter of instance methods (though you don’t pass it explicitly when calling the method).
class Person: def __init__(self, name: str, age: int): # self refers to the current instance self.name = name # Instance attribute self.age = age # Instance attribute
def introduce(self): # self allows access to instance attributes return f"Hi, I'm {self.name} and I'm {self.age} years old"
person = Person("Alice", 30)print(person.introduce()) # "Hi, I'm Alice and I'm 30 years old"Hi, I'm Alice and I'm 30 years oldInstance Attributes
Section titled “Instance Attributes”Instance attributes are variables that belong to a specific instance. Each object has its own copy of these attributes.
class BankAccount: def __init__(self, account_number: str, balance: float): # Instance attributes - unique to each account self.account_number = account_number self.balance = balance
# Each account has its own balanceaccount1 = BankAccount("ACC-001", 1000.0)account2 = BankAccount("ACC-002", 500.0)
print(account1.balance) # 1000.0print(account2.balance) # 500.01000.0500.0Instance Methods
Section titled “Instance Methods”Instance methods are functions defined inside a class that operate on instance data. They always take self as the first parameter.
class BankAccount: def __init__(self, account_number: str, balance: float): self.account_number = account_number self.balance = balance
def deposit(self, amount: float): """Instance method - operates on this account""" if amount > 0: self.balance += amount return f"Deposited ${amount:.2f}. New balance: ${self.balance:.2f}" return "Invalid deposit amount"
def withdraw(self, amount: float): """Instance method - operates on this account""" if 0 < amount <= self.balance: self.balance -= amount return f"Withdrew ${amount:.2f}. New balance: ${self.balance:.2f}" return "Insufficient funds or invalid amount"
def get_balance(self): """Instance method - returns this account's balance""" return self.balance
# Usageaccount = BankAccount("ACC-001", 1000.0)print(account.deposit(500.0)) # Deposited $500.00. New balance: $1500.00print(account.withdraw(200.0)) # Withdrew $200.00. New balance: $1300.00print(account.get_balance()) # 1300.0Deposited $500.00. New balance: $1500.00Withdrew $200.00. New balance: $1300.001300.0Complete Example: User Class
Section titled “Complete Example: User Class”Let’s put it all together with a complete example:
class User: """A simple User class demonstrating basic OOP concepts"""
def __init__(self, username: str, email: str, age: int): """Constructor - initialize user attributes""" self.username = username self.email = email self.age = age self.is_active = True # Default value
def get_info(self): """Instance method - return user information""" status = "active" if self.is_active else "inactive" return f"User: {self.username} ({self.email}), Age: {self.age}, Status: {status}"
def deactivate(self): """Instance method - deactivate user account""" self.is_active = False return f"{self.username} has been deactivated"
def activate(self): """Instance method - activate user account""" self.is_active = True return f"{self.username} has been activated"
def update_email(self, new_email: str): """Instance method - update user email""" if "@" in new_email: self.email = new_email return f"Email updated to {new_email}" return "Invalid email address"
# Create user instancesuser1 = User("alice", "alice@example.com", 25)user2 = User("bob", "bob@example.com", 30)
# Each user is independentprint(user1.get_info())print(user2.get_info())
# Modify one user - doesn't affect the otheruser1.deactivate()print(user1.get_info())print(user2.get_info())User: alice (alice@example.com), Age: 25, Status: activeUser: bob (bob@example.com), Age: 30, Status: activeUser: alice (alice@example.com), Age: 25, Status: inactiveUser: bob (bob@example.com), Age: 30, Status: activeclassDiagram
class User {
-username: str
-email: str
-age: int
-is_active: bool
+__init__(username, email, age)
+get_info() str
+deactivate() str
+activate() str
+update_email(new_email) str
}
note for User "Class: Blueprint\nInstance: Specific user"
Real-World Example: Product Class
Section titled “Real-World Example: Product Class”class Product: """Product class for an e-commerce system"""
def __init__(self, name: str, price: float, sku: str): """Initialize product with name, price, and SKU""" self.name = name self.price = price self.sku = sku self.stock = 0 # Default stock level
def add_stock(self, quantity: int): """Add items to stock""" if quantity > 0: self.stock += quantity return f"Added {quantity} units. Stock: {self.stock}" return "Invalid quantity"
def sell(self, quantity: int): """Sell items from stock""" if quantity <= 0: return "Invalid quantity" if quantity > self.stock: return f"Insufficient stock. Available: {self.stock}" self.stock -= quantity return f"Sold {quantity} units. Remaining stock: {self.stock}"
def get_total_value(self): """Calculate total value of current stock""" return self.stock * self.price
def display_info(self): """Display product information""" return f"{self.name} (SKU: {self.sku}) - ${self.price:.2f} | Stock: {self.stock}"
# Usagelaptop = Product("Laptop", 999.99, "LAP-001")mouse = Product("Mouse", 29.99, "MOU-001")
# Each product is independentlaptop.add_stock(10)mouse.add_stock(50)
print(laptop.display_info())print(mouse.display_info())
laptop.sell(3)print(laptop.get_total_value()) # 6999.93 (7 laptops * $999.99)Added 10 units. Stock: 10Added 50 units. Stock: 50Laptop (SKU: LAP-001) - $999.99 | Stock: 10Mouse (SKU: MOU-001) - $29.99 | Stock: 50Sold 3 units. Remaining stock: 76999.93## Key Concepts Summary
### 1. Class Definition```pythonclass ClassName: # Class body pass2. Constructor (__init__)
Section titled “2. Constructor (__init__)”def __init__(self, param1, param2): self.attribute1 = param1 self.attribute2 = param23. Instance Methods
Section titled “3. Instance Methods”def method_name(self, param1, param2): # Method body # Access instance attributes with self.attribute return result4. Creating Instances
Section titled “4. Creating Instances”instance = ClassName(arg1, arg2)5. Accessing Attributes and Methods
Section titled “5. Accessing Attributes and Methods”instance.attribute # Access attributeinstance.method() # Call methodCommon Patterns
Section titled “Common Patterns”Pattern 1: Initialization with Defaults
Section titled “Pattern 1: Initialization with Defaults”class User: def __init__(self, username: str, email: str, age: int = 18): """Age has a default value""" self.username = username self.email = email self.age = age
user1 = User("alice", "alice@example.com") # Uses default ageuser2 = User("bob", "bob@example.com", 25) # Overrides default agePattern 2: Methods That Return Information
Section titled “Pattern 2: Methods That Return Information”class Rectangle: def __init__(self, width: float, height: float): self.width = width self.height = height
def area(self): """Calculate and return area""" return self.width * self.height
def perimeter(self): """Calculate and return perimeter""" return 2 * (self.width + self.height)
rect = Rectangle(5, 3)print(rect.area()) # 15print(rect.perimeter()) # 161516Pattern 3: Methods That Modify State
Section titled “Pattern 3: Methods That Modify State”class Counter: def __init__(self, initial_value: int = 0): self.value = initial_value
def increment(self): """Modify the counter value""" self.value += 1
def decrement(self): """Modify the counter value""" self.value -= 1
def reset(self): """Reset to zero""" self.value = 0
counter = Counter(10)counter.increment()print(counter.value) # 11counter.decrement()print(counter.value) # 10counter.reset()print(counter.value) # 011100Visual Representation
Section titled “Visual Representation”Key Takeaways
Section titled “Key Takeaways”Next Steps
Section titled “Next Steps”Now that you understand the basics of classes, you’re ready to explore:
- Encapsulation - Protecting data with access modifiers
- Inheritance - Creating class hierarchies
- Polymorphism - Using objects interchangeably
- Advanced features - Properties, static methods, and more
Remember: Classes are a way to model real-world entities in code, bundling together related data (attributes) and behavior (methods) into a single, reusable unit.