Classes
A class bundles data with the functions that work on it. Each object, or instance, has its own attributes.
class Dog:
legs = 4 # shared by all dogs
def __init__(self, name):
self.name = name # per dog
def speak(self):
return f"{self.name}: woof"
def __repr__(self):
return f"Dog({self.name!r})"__init__ sets up a new object. self is that object, and Python passes it for you when you call rex.speak(). __repr__ controls how the object appears when printed in a list or a debugger.
Inheritance
class Puppy(Dog):
def __init__(self, name, age):
super().__init__(name)
self.age = agePuppy gets every Dog method and can add or replace them. super() calls the parent version. Keep hierarchies shallow. Often a plain function or a stored object is simpler.
Your task
Write Wallet(owner, balance=0) with deposit(amount) and withdraw(amount), each returning the new balance and raising ValueError for a non-positive amount or, for withdraw, too little money. Its repr is Wallet('Ada', 10). Write SavingsWallet(Wallet) taking rate=0.1, with add_interest() adding balance * rate.
The explanation opens here once every check passes.