Skip to content
Forge Learn/Object-Oriented Python
Browsing as a guest. Sign in to save your progress and earn XP as you complete chapters.

Classes, Objects & __init__

7 min read

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.

A minimal class with __init__

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.

A BankAccount class with three methods
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"
Using the BankAccount class
  • -`__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.