Courses/Python Mastery/Module 9: Object-Oriented Python
Module 9 · Lesson 320 minBeginner

Inheritance — Build on What Exists

Lesson goal
Extend classes without rewriting them.

Inheritance — Build on What Exists

Every app has things that are *alike but not identical*: a Car and a Bike are both Vehicles; a Dog and a Cat are both Animals; a TextPost and a VideoPost are both Posts. Inheritance lets one class reuse another's code and then add its own twist.

The syntax: one parenthesis

code
class Animal:                          # the PARENT (base) class
    def __init__(self, name):
        self.name = name

    def eat(self):
        print(f"{self.name} is eating")

    def sleep(self):
        print(f"{self.name} is sleeping")


class Dog(Animal):                     # the CHILD — inherits from Animal
    def bark(self):
        print(f"{self.name} says Woof!")


class Cat(Animal):
    def meow(self):
        print(f"{self.name} says Meow")

class Dog(Animal) reads: *"Dog is an Animal, plus more."* Dogs get eat() and sleep() for free, plus their own bark():

code
d = Dog("Rocky")
c = Cat("Whiskers")

d.eat()        # Rocky is eating     ← inherited from Animal
d.bark()       # Rocky says Woof!    ← Dog's own
c.eat()        # Whiskers is eating  ← inherited
c.bark()       # AttributeError! — Cats don't bark

The parent's code written once, used by every child. Add a play() method to Animal and instantly all pets can play.

Overriding — the child's twist

Children can replace inherited methods with their own version:

code
class Bird(Animal):
    def eat(self):                       # same name as parent's
        print(f"{self.name} pecks at seeds")

b = Bird("Tweety")
b.eat()      # Tweeety pecks at seeds — Bird's version wins

Python uses the child's method if it exists; the parent's is only a fallback. This is called overriding, and it's how "all animals eat, but each in their own way" becomes code.

super() — extending without replacing

Often you don't want to *replace* the parent's behavior — you want to add to it. super() calls the parent's version:

code
class Dog(Animal):
    def __init__(self, name, breed):     # Dog needs an EXTRA field
        super().__init__(name)           # let Animal handle name
        self.breed = breed               # then handle the extra

    def eat(self):
        super().eat()                    # do the normal eating...
        print(f"{self.name} wags its tail")   # ...then Dog's extra

d = Dog("Rocky", "Labrador")
print(d.breed)     # Labrador
d.eat()
# Rocky is eating
# Rocky wags its tail

super().__init__(name) is the professional pattern you'll see in every framework: let the parent set up its part, then set up yours. Without it, the child would have to re-implement all the parent's setup.

The is-a test (when to inherit)

Inheritance models "is a" relationships:

  • Dog is an Animal ✅
  • Car is a Vehicle ✅
  • Student has a Course ❌ — that's *composition* (a Student object containing a Course object as an attribute), not inheritance
  • Quick test: say it out loud. "Cat is an Animal" sounds right. "Course is a Student" sounds absurd. If the sentence fails, don't inherit — store the object as an attribute instead.

    Common Errors & Fixes

  • `TypeError: Dog() takes no arguments` — the child has no __init__ but you passed arguments; the parent's __init__ expects only self+name. Add a child __init__ with super().__init__().
  • Forgot super().__init__() — child's __init__ replaces the parent's entirely; parent attributes never get set. Always call super first.
  • `AttributeError` on an inherited method — check the spelling, and confirm the class actually inherits from the right parent.

  • ✅ Checkpoint

  • What does class Dog(Animal) mean? *(Dog inherits from Animal — gets all its methods)*
  • What's overriding? *(Child redefining a parent's method with its own version)*
  • What does super().__init__(name) do? *(Runs the parent's setup, so the child doesn't repeat it)*
  • Student "has a" Course — inheritance? *(No — store the Course as an attribute instead)*
  • Next: dunder methods — making your objects work with print, len, and comparison.