Classes, Objects & __init__
You'll learn to
- -Explain the difference between a class (a blueprint) and an object (an instance built from it)
- -Write a class with an `__init__` method that sets up instance attributes
- -Create multiple independent instances of the same class and call methods on them
Everything up to this point has been about individual values and functions that operate on them. A class lets you bundle data and the functions that operate on that data into a single unit, and it is the single most important idea in the rest of this course. Nearly every early Forge Algorithm Lab level, building a stack, a queue, a hash map, a linked list, asks you to define a class, which is exactly why this module gets more depth than any other in Phase 1.
Class vs. Object
A class is a blueprint. It describes what data an object of that type will hold and what it can do. An object, or "instance," is one concrete thing built from that blueprint. int is a class; 5 is an object (instance) of that class. You have been using classes and objects since the first chapter of this course without naming them. Every list, string, and dict you have created is an instance of a class.
Defining a Class
A class is defined with the class keyword. The special method __init__ runs automatically whenever a new instance is created, and its job is to set up that instance's starting state. self is the instance being created or operated on. It is the first parameter of every instance method, and Python passes it in automatically. You never supply it yourself at the call site.
Notice the parallel to the closure example from the previous module. make_counter() returned a function that remembered a private count. A class does the same job in a more structured, extensible way. self.count is that private state, and it is available to every method on the class, not just one.
A Larger Worked Example: BankAccount
Let's build something with more than one piece of state and more than one method, since that is the shape every real Forge Algorithm Lab class-based level takes.
class BankAccount:
def __init__(self, owner, balance=0):
self.owner = owner
self.balance = balance
self.transaction_count = 0
def deposit(self, amount):
if amount <= 0:
raise ValueError("Deposit amount must be positive")
self.balance += amount
self.transaction_count += 1
def withdraw(self, amount):
if amount > self.balance:
raise ValueError("Insufficient funds")
self.balance -= amount
self.transaction_count += 1
def summary(self):
return f"{self.owner}: ${self.balance} across {self.transaction_count} transactions"- -__init__ is called automatically by ClassName(...). You never call it directly.
- -Every attribute your instance will use should generally be set in __init__, even if just to a default like 0 or None. This avoids "attribute doesn't exist yet" bugs later.
- -Each instance (each BankAccount(...) call) gets its own independent copy of self.balance and self.transaction_count.
A useful mental model: __init__ is just a regular function, except Python calls it for you at creation time and quietly passes in the new, empty object as self for you to fill in.
Interview Signal is part of Pro
See a real weak answer next to a real strong one for this exact topic.
Quiz is part of Pro
Test what you just read with a short quiz, and bank the XP.
Discussion0
Join the Discussion
Sign in to leave comments, reply to others, or like insights.
No comments yet. Be the first to start the thread!