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.
- -`__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.