Pebellslearn by building
0%
RoadmapMatrixCatalogSandboxSign in
Objects  ›  Lesson

Inheritance

Inheritance 16 minSpecialising a type: writing down only what differs from its parent
You're building a piece ofA bank account that can't go wrong
This piece — SavingsAccount: Everything an account does, plus interest.
Scenario The bank launches a savings product. It behaves exactly like a current account, plus interest — and nobody wants to rewrite deposit().
Your task
Define Account with deposit(amount), then SavingsAccount(Account) adding add_interest() which increases the balance by its rate. Write savings_after(start, rate, years) which applies interest once per year and returns the balance rounded to 2 decimals. Example: savings_after(100, 0.1, 2) → 121.0.

Inheritance

The bank wants a savings account. It behaves exactly like the account you already built — same owner, same balance, same deposit — plus interest.

You could copy the class and add a method. Then every fix to withdraw has to be made twice, and one day it won't be. Inheritance says it differently: a savings account is an account, with one addition.


A subclass writes down only the difference

python

SavingsAccount never defines __init__ or deposit — it gets both. The parent goes in the parentheses, and that's the whole declaration.

Extending the parent's setup with super()

When the child needs its own state too, call up to the parent first:

python

Skip that super() call and the parent's setup never runs — so the attributes it would have created simply don't exist:

broken — fix itAttributeError

Run it and read the error — it's telling you an attribute is missing. Then make it print 0.

Overriding: replace, or build on

A child can redefine a method outright, or reuse the parent's result:

python

super().summary() runs the parent's version and then decorates it — so an improvement upstream still reaches the child.


A first taste: one loop, many types

Here's the payoff, and it has a name — polymorphism, the next lesson's whole subject. This loop never asks what kind of account it's holding:

python

Adding a third product means writing a third class. The loop doesn't change — that's the property worth having, and it's why "which type is this?" checks are a smell in object code.

Python takes this further than most languages: it never checked that either type inherited from anything. It only needed monthly() to exist.

What does this print?
class Duck:
    def speak(self): return "Quack"

class Robot:
    def speak(self): return "Beep"

print(" ".join(x.speak() for x in [Duck(), Robot()]))

Watch the two monthly() calls resolve to different code from the same line:

step through it
1class Account:
2 def __init__(self, balance):
3 self.balance = balance
4 def monthly(self):
5 return self.balance
6 
7class Savings(Account):
8 def monthly(self):
9 self.balance += self.balance * 0.1
10 return self.balance
11 
12plain = Account(100)
13saver = Savings(100)
14plain.monthly()
15saver.monthly()
16print(plain.balance, saver.balance)

🎯 Your turn

Define Account with deposit(amount), then SavingsAccount(Account) adding a rate and add_interest(). Write savings_after(start, rate, years) applying interest once per year and returning the balance rounded to two decimals:

  • savings_after(100, 0.1, 2)121.0
  • savings_after(100, 0.1, 0)100.0

Hint — super().__init__(owner, balance) first, then self.rate. Round only at the very end.

Then press ▶ Run and hit ✓ Check. ✅

Practice — level up

0/5 solved

Solve each in its own editor — Run to try, Check to grade. Stuck? Reveal a Hint, or the full Solution + walkthrough.

Warm-upA subclass that adds one thing

Define Animal with a name and a speak() returning "...". Define Dog(Animal) overriding speak() to return "Woof". Write dog_says(name) returning what a Dog says.

inheritance
DrillExtending the parent's setup

Define Vehicle storing wheels. Define Car(Vehicle) whose __init__ calls super().__init__(4) and also stores brand. Write car_wheels(brand) returning the wheel count.

inheritancesuper
BuildOne loop, several types

Given Cat and Cow both with speak() ("Meow" / "Moo"), write chorus() returning "Meow Moo" by looping over a list holding one of each and joining what they say. The loop must not check which type it has.

polymorphismloop
BossOverride, then call up

Define Logger with line(msg) returning msg. Define Loud(Logger) whose line returns the parent's result upper-cased with "!" appended. Write shout(msg) returning Loud().line(msg).

inheritancesuperoverride
CapstoneTwo accounts, one interface

Define Account(balance) with monthly() returning the balance unchanged, and Savings(Account) whose monthly() adds 1% . Write year_end(balances) where each entry is ["plain", 100] or ["savings", 100], applying monthly() twelve times to each and returning the list of balances rounded to 2 decimals.

inheritancepolymorphismsuperloop
savings_after.py
Call the function you wrote — just like your app's frontend would. Edit the inputs and hit Call.
savings_after(start, rate, years) → floatCompound the interest once per year; return the balance.
try:
returned
Press Run to execute your code.
Press Check to run the tests for this lesson.
Inheritance — Pebells