Classes & Instances
Everything you've built so far keeps data on one side and functions on the other. A dict holds the account; separate functions do things to it. That works right up until the moment someone forgets to call the checking function.
Objects close that gap. A class is a template that bundles data with the functions allowed to touch it — and once they live together, you can start making promises about the data that the rest of the program cannot break.
We'll build a bank account across this section. This lesson gets it opened.
A class is a template; an instance is a thing
__init__ runs automatically when you call Account("Ada", 100). It isn't the
constructor exactly — the object already exists by then — it's the setup, the
place you hang values off it.
self is the object being worked on
This is the part that feels strange coming from other languages, so let's be blunt
about it: self is just the first parameter, and Python passes it for you.
ada.deposit(50) is really Account.deposit(ada, 50).
Notice deposit returns nothing. It doesn't need to — it changed the object, and
the object is what everyone is holding.
Forget self and the error is confusing, so meet it now:
TypeErrorRun it and read the error carefully. It's counting arguments. Then fix the signature.
Each instance has its own state
This is the whole reason to bother:
class Account:
def __init__(self, owner, balance=0):
self.owner = owner
self.balance = balance
def deposit(self, amount):
self.balance += amount
a = Account("Ada")
b = Account("Bea")
a.deposit(100)
print(b.balance)Watch two accounts live side by side, and see self bind to a different object on
each call:
Methods can return things too
deposit mutates. A method can just as well compute and hand something back:
summary() takes no arguments beyond self because everything it needs is
already attached. That's the shape you're aiming for — methods that read like
questions you'd ask the object.
One trap worth avoiding today
Attributes belong in __init__, not on the class body, whenever they're mutable:
class Basket:
items = [] # shared by EVERY basket
def add(self, thing):
self.items.append(thing)
a = Basket()
b = Basket()
a.add("soup")
print(len(b.items))🎯 Your turn
Define an Account class with __init__(self, owner, balance=0) and a
deposit(self, amount) method. Then write account_balance(owner, deposits)
which opens an account, deposits each amount in turn, and returns the balance:
account_balance("Ada", [100, 50])→150account_balance("Sam", [])→0
Hint — store self.owner and self.balance in __init__; deposit is one
line; build the account once and loop.
Then press ▶ Run and hit ✓ Check. ✅
