fbpx
Inheritance Python

Inheritance in Python + Harry Potter Example

You have the eyes of your mother.

One could say, you “inherited” the eyes of your mother.

As you may have guessed, this article is about inheritance in Python.

Inheritance is one of the main motivators of using object orientation. It’s a simple and intuitive concept but even advanced coders circumvent using inheritance because they have this latent feeling of not understanding it 100%. This harms their ability to write clean and effective code, and–ultimately — harms their ability to operate on their full potential. Do you think you could do more to live up to your potential? Good. Then, let’s start learning inheritance in Python.

Let’s have a look at a bad example NOT using inheritance. Keep your code understanding skills fresh by solving the puzzle first before you read on.

class Human:


    def __init__(self, name, ff, iq):
        self.name = name
        self.ff = ff # = facebook friends
        self.iq = iq

    def befriend(self, other):
        self.ff += 1
        other.ff += 1

    def learn(self):
        self.iq += 1



class Wizard:


    def __init__(self, name, ff, iq, mana):
        self.name = name
        self.ff = ff # = facebook friends
        self.iq = iq
        self.mana = mana

    def befriend(self, other):
        self.ff += 1
        other.ff += 1

    def learn(self):
        self.iq += 1
    
    def magic_friends(self, num):
        self.ff += num if self.mana>0 else 0
        self.mana -= 100


vernon = Human("Vernon", 0, 80)
tom = Wizard("Tom", 666, 130, 100)
dumbledore = Wizard("Albus", 999, 189, 100)

dumbledore.befriend(tom)
dumbledore.befriend(vernon)
dumbledore.magic_friends(100)

print("Friends Vernon: " + str(vernon.ff))
print("Friends Tom: " + str(tom.ff))
print("Friends Dumbledore: " + str(dumbledore.ff))

Before you read on, I have two questions for you:

  1. What is the output of the above code snippet?
  2. What’s your idea of making this code more concise?

What is the output of the above code snippet?

Let’s start with the first question. We create two classes Human and Wizards. Both have very similar methods and attributes. The only difference is that the Wizard class has one additional attribute (self.mana) and one additional method (magic_friends). Both methods befriend and magic_friends modify the instance attribute ff. By hacking Facebook, Dumbledore gains 100 additional friends (plus Vernon plus Tom).

Thus, the result is:

"""
Friends Vernon: 1
Friends Tom: 667
Friends Dumbledore: 1101
"""

What’s your idea of making this code more concise?

Regarding the second question, I have already indicated the problem: there are huge redundancies between the two classes Human and Wizard. Most methods and attributes are exactly the same. The reason is that, conceptually, a Wizard is also Human. And every human needs to have an IQ, a Facebook account, and a name (as you know).

In other words: Every Wizard is a Human but not every Human is a Wizard.

How can we express this fact in Python object orientation?

The answer is inheritance.

We create a class Human and a class Wizard. The class Wizard is the “child class” of the “parent class” Human. In this way, the child class Wizard “inherits” every attribute and method from the parent class Human. This saves us all the redundant definitions and initializations in the Wizard class. See the example:

class Human:


    def __init__(self, name, ff, iq):
        self.name = name
        self.ff = ff # = facebook friends
        self.iq = iq

    def befriend(self, other):
        self.ff += 1
        other.ff += 1

    def learn(self):
        self.iq += 1



class Wizard(Human):


    def __init__(self, name, ff, iq, mana):
        super().__init__(name, ff, iq)
        self.mana = mana

    def magic_friends(self, num):
        self.ff += num if self.mana>0 else 0
        self.mana -= 100


vernon = Human("Vernon", 0, 80)
tom = Wizard("Tom", 666, 130, 100)
dumbledore = Wizard("Albus", 999, 189, 100)

dumbledore.befriend(tom)
dumbledore.befriend(vernon)
dumbledore.magic_friends(100)

print("Friends Vernon: " + str(vernon.ff))
print("Friends Tom: " + str(tom.ff))
print("Friends Dumbledore: " + str(dumbledore.ff))

dumbledore.learn()
print("IQ Dumbledore: " + str(dumbledore.iq))

The result is exactly the same as above. As you can see in the last two lines, Dumbledore can still call the method learn() — even though it is not defined in the Wizard class. The reason is that the Wizard class inherits all methods and attributes from the Human class. Can you find where we define the inheritance in the code?

One final note: in the constructor of the Wizard class, we call the constructor of the parent class using “super()”. This initializes the variables in exactly the same way as the parent constructor from the Human class.

Where to go from here?

Strategy beats tactics in the long run. You need to have a learning strategy in place to master Python. Do you?

If not, get a quick win by downloading our popular Python cheat sheets (high-res PDF), as well as the long-term solution to your problem (almost daily Python lessons). It’s 100% free. No Spam. Guaranteed.

Leave a Comment

Your email address will not be published. Required fields are marked *