Modules -> OOP -> Inheritance -> Inheritance

Inheritance


Related code
class Dog:
    def __init__(self, name, age, energy):
        self.name = name
        self.age = age
        self.energy = energy

    def __str__(self):
        return f"{self.name} is {self.age} years old."

    def play(self, hours):
        self.energy -= hours * 10

    def sleep(self, hours):
        self.energy += hours * 10

    def bark(self):
        print(f"{self.name} is barking")

    def guard(self):
        return f"{self.name} is guarding the house."


class Cat:
    def __init__(self, name, age, energy):
        self.name = name
        self.age = age
        self.energy = energy

    def __str__(self):
        return f"{self.name} is {self.age} years old."

    def play(self, hours):
        self.energy -= hours * 10

    def sleep(self, hours):
        self.energy += hours * 10

    def meow(self):
        return f"{self.name} is meowing."

    def climb(self):
        print(f"{self.name} is climbing a tree.")

In the code above, both Dog and Cat share three common attributes and four common methods.

Repetition in code is something we generally want to avoid. In the example above, we repeated many attributes and methods in both the Dog and Cat classes. There should be a reason why dogs and cats share many characteristics and behaviors; they both belong to the same category: animals.

This is where inheritance, a core concept of Object-Oriented Programming (OOP), comes in. Inheritance allows us to define a parent class (in this case, Animal) that contains the shared attributes and methods. Then, we create child classes (Dog and Cat) that inherit from the parent class, avoiding duplication and making the code cleaner and more maintainable.

class Animal:
    def __init__(self, name, age, energy):
        self.name = name
        self.age = age
        self.energy = energy

    def __str__(self):
        return f"{self.name} is {self.age} years old."

    def play(self, hours):
        self.energy -= hours * 10

    def sleep(self, hours):
        self.energy += hours * 10


class Dog(Animal):
    def bark(self):
        print(f"{self.name} is barking")

    def guard(self):
        return f"{self.name} is guarding the house."


class Cat(Animal):
    def meow(self):
        return f"{self.name} is meowing."

    def climb(self):
        print(f"{self.name} is climbing a tree.")

Syntax: In the class definition header, immediately after the class name, you put the name of the class you want to inherit from inside parentheses.

Now Dog and Cat has all of the following methods: __init__, __str__, play and sleep, inherited from Animal, plus each of them has two more methods. Dog barks and sleeps, cat meows and climbs.

>>> d = Dog("Murki", 3, 60)
>>> c = Cat("Nina", 2, 90)
>>> d.play(1)
>>> d.energy
50
>>> c.play(1)
>>> c.energy
80
>>> d.bark()
Murki is barking
>>> c.climb()
Nina is climbing a tree.

Dog doesn't climb, and cat doesn't guard:

>>> d.climb()
AttributeError("'Dog' object has no attribute 'climb'")
>>> c.guard()
AttributeError("'Cat' object has no attribute 'guard'")