Lesson 7 of 11
A child class can override a parent method by defining one with the same name. Python finds the child's version first, so that's the one that runs.
class Animal:
def __init__(self, name):
self.name = name
def speak(self):
return f"{self.name} makes a sound."
class Dog(Animal):
def speak(self):
return f"{self.name} says woof!"
class Cat(Animal):
def speak(self):
return f"{self.name} says meow!"
print(Animal("Generic").speak())
print(Dog("Rex").speak())
print(Cat("Whiskers").speak())
super() — extending instead of replacing
Overriding throws the parent's version away. Often you want to add to it instead. super()
gives you the parent's version.
class Animal:
def describe(self):
return "I am an animal."
class Dog(Animal):
def describe(self):
base = super().describe()
return f"{base} Specifically, a dog."
print(Dog().describe())
super().__init__()
This is where super() matters most. A child that defines its own __init__ replaces the
parent's — so the parent's setup never runs:
class Animal:
def __init__(self, name):
self.name = name
class Dog(Animal):
def __init__(self, name, breed):
self.breed = breed
rex = Dog("Rex", "Labrador")
print(rex.breed)
print(rex.name)
That raises AttributeError — nothing ever set self.name. Call the parent's __init__ first:
class Animal:
def __init__(self, name):
self.name = name
class Dog(Animal):
def __init__(self, name, breed):
super().__init__(name)
self.breed = breed
rex = Dog("Rex", "Labrador")
print(rex.name)
print(rex.breed)
The pattern is always the same: super().__init__(...) first with whatever the parent needs,
then the child's own extra attributes.
Why super() and not Animal.__init__(self, name)
Both work, but super() is better:
- The parent's name isn't hardcoded, so renaming or re-parenting doesn't break the child.
- You don't pass
selfmanually. - It handles multiple inheritance correctly.
A worked example
class BankAccount:
def __init__(self, owner, balance=0):
self.owner = owner
self.balance = balance
def describe(self):
return f"{self.owner}: {self.balance}"
class SavingsAccount(BankAccount):
def __init__(self, owner, balance=0, rate=0.02):
super().__init__(owner, balance)
self.rate = rate
def add_interest(self):
self.balance += self.balance * self.rate
def describe(self):
return f"{super().describe()} (savings at {self.rate})"
acct = SavingsAccount("Ada", 1000)
acct.add_interest()
print(acct.balance)
print(acct.describe())
SavingsAccount extends both __init__ and describe(), reusing the parent's work in each
rather than duplicating it.
Try it yourself
Override speak() in Dog, and extend describe() with super().
Checkpoint
- Defining a method with the parent's name overrides it.
super()reaches the parent's version so you can extend rather than replace.- A child
__init__must callsuper().__init__(...)or the parent's setup is skipped. - Prefer
super()over naming the parent class directly.
Questions about this lesson
Log in to ask a question.