Python Inheritance Tutorial: classes like a pro

Share This Post

No doubt Python is a powerful language: with a few lines of code, you can solve big problems. This is possible because of abstraction, the possibility to represent complex data. We already started working on this topic with classes, a great way to model advanced data. However, today we are going to move one step further. In this Python Inheritance Tutorial, we are going to see how you can relate classes with one another so that they share behavior. By now it might seem fuzzy, but read now and everything will become clear.

Python Inheritance in Simple Terms

Python Inheritance has advanced applications, but understanding it is very easy. However, for that, you need to have a solid understanding of Python classes (if you don’t, here’s a quick reading).

Imagine you want to represent People in your system. In fact, let’s say you want to have your program handle people in a school. You can model the class Person so that it contains all the basic information, like name, surname and home address. However, in a school you are going to have students and teachers. Therefore, you should model two separate entities: Student and Teacher. The student will contain information about the courses he is following, while the teacher about the courses he is teaching. To add some extra flavor, let’s pretend we also need to add salary details for the teacher, and we don’t need them on the Student of course.

We also need the basic information on both Student and Teacher, but why replicating them in each? After all, a Student is a Person, a Teacher is a person. This is when inheritance comes into play, and here we have the definition.

With Inheritance, a class obtains (inherits) the methods and attributes from another class. By instantiating an object of this child class, you will be able to use parent attributes and methods on it.

Some terminology about Python Inheritance

As you can see, the concept is simple. However, to understand it better, you need to have the inheritance jargon. Even this is simple after all.

  • The child class (or subclass) is the class that is obtaining attributes and methods from the other.
  • Instead, the parent class (or superclass), is the class that is giving attributes and methods to the other.
  • The super constructor is the constructor of the parent class, as seen from the child class.
  • Extending a class means creating a child class that inherits from it.

Generally speaking, we can say that the word super refers to the parent class. This is especially true in Python Inheritance, because super is a keyword.

A visual example

The best way to make the point in this Python Inheritance Tutorial is with a visual example. Remember the Person-Student-Teacher problem we just faced in the introduction, here’s what the logic behind will look like.

Python inheritance tutorial to understand how to write scalable and better classes
Python Inheritance visualization.

As you can see, we define three separate entities. However, if you look at the colors, you will see that we can access the attributes from Person in both Student and Teacher, the blue ones. We didn’t define them either in Student nor Teacher, they took them from Person.

The code of Python Inheritance

Getting our feet wet

We should start with the simplest possible inheritance: a class that passively inherit from another. In this case, we simply access methods and attributes from the superclass, and nothing more than that. The best example for that is, indeed, our Person-Student-Teacher problem.

To define that a class inherits from another, write the parent class name in brackets in the child class declaration.

In other words, write something like that:

def ChildClass(ParentClass):
  # Child class code...

With this in mind, you can quickly model our famous problem.

class Person:
  def __init__(self, name, surname, address):
    self.name = name
    self.surname = surname
    self.address = address
    
    
class Student(Person):
  followed_courses = []
  
  def __init__(self):
    pass

class Teacher(Person):
  teaching_in_courses = []
  salary_info = {}
  
  def __init__(self):
    pass

This code has a problem. When we instantiate a Student or Teacher object, we don’t call the super constructor. Instead, we simply call Student and Teacher constructors, and they don’t do anything. We will solve this later on, don’t worry!

Multiple Inheritance

Any modern language will have classes and Inheritance. However, Python goes further with Multiple Inheritance: not all languages have it. This makes Python Inheritance more powerful and even a little bit mind-blowing in some cases.

Multiple Inheritance happens when a child class has two or more parent classes.

The uses for this approach are rare, but in some very dire circumstances, this feature is going to save you. In this example, we could model a new class Employee with salary information, and have the Teacher inherit from both Person and Employee. This is possible and will work like a charm. However, it is not the best design choice. Since each employee must be a person (not hiring robots so far!), and each teacher must be an employee, the correct model would be Employee that inherits from Person and Teacher that inherits from Employee. In this case, however, we wouldn’t have multiple inheritances. In order to have that, a child class must inherit from two direct parents at the same time.

Writing a relationship of multiple inheritance is as easy as adding a comma.

class Teacher(Person, Employee):
  # The code goes here

This, however, adds some caveats. What if Person and Employee define the same attributes? They shouldn’t, otherwise, we have the risk of shadowing (hiding) some of them. Nonetheless, this is advanced programming and we don’t have to worry about it. With practice and experience, you will learn how to implement multiple inheritance in the right way.

This is.. super!

Now it is time to introduce our super-awesome keyword: super. Like self allows us to access methods and attributes of this object, super allows us to do that from our superclass.

However, it is a little bit different from self. In fact, super is a function and it wants to know the desired parent class and the object from which to extract methods and attributes. It needs the parent class because we might have multiple parents, so it needs to know what is the one we want to access the methods of. And, of course, it needs the object because it needs to know what is the child from which to extrapolate the parent. In many cases, this reference will point to self.

Thus, we can write this code so that the Student class calls the __init__() from Person.

class Person:
  def __init__(self, name, surname, address):
    self.name = name
    self.surname = surname
    self.address = address
    
    
class Student(Person):	
  def __init__(self, name, surname, address followed_courses):
    super(Person, self).__init__(name, surname, address)
    self.followed_courses = followed_courses

In case it isn’t clear, the line that calls the super constructor is super(Person, self).__init__(name, surname, address).

Abstract Classes

An abstract class that does not allow the creation of objects directly. Instead, it must be extended by some child class. While some programming languages have a way of saying “Okay, this class is abstract”, Python does not do that. If we want to achieve this, we need to make it impossible to instantiate the class. To do that, we simply raise a NotImplementedError in the constructor.

For example, in our system, we might want to have Students and Teachers, but no instance of Person. Thus, instead of having the constructor do something, we can write it like this.

class Person:
  name = ""
  surname = ""
  address = ""
  
  def __init__(self, name, surname, address):
    raise NotImplementedError()

Now, take your abstract classes one step further. You can use them to create a template. For example, you can say “I want your class to have at least these methods” with an abstract class. Simply write all the methods in an abstract class, then have other developers extend it. This can be important when you are writing drivers that will control peripheral or streams. You want to be able to call all the functions you need on all the drivers.

Learn to use abstract classes even if you are developing alone. They make your code easier to maintain and extend.

Checking the parent classes

Python offers two awesome functions to verify inheritance and classes in general: type() and isinstance(). They behave in two different ways, making them unique for our code.

  • type() returns the type of object, that is: its class. It does not consider any superclass.
  • Instead, isinstance() compares an object with a class and returns true if the object is an instance of this class, or subclass.

So, to make an example with our data:

>>> type(Person('John', 'Doe', 'Temple Bar')) == type(Student('John', 'Doe', 'Temple Bar', []))
false
>>> isinstance(Student('John', 'Doe', 'Temple Bar', []), Person)
true

This is handy, especially if you are working with abstract classes. This way you can ensure that you are instantiating an object that is inheriting from the right abstract class, thus having all the methods you need.

The benefits of Inheritance

For this Python Inheritance Tutorial, understanding inheritance is not enough. We also need to know what are the true benefits of using it. Well, they are all related to scale and maintain your code. Take a look at these bullet points.

  • Centralize the definition of data structure, instead of replicating the same data every time
  • Segment your code into smaller modules (each subclass), making it easy to read and to modify, as you have to alert only the individual component
  • Better representation of real-world entities (like Student and Teacher)
  • Segmenting your code helps you to contain it into smaller files, more human-sized

Wrapping it up

In this Python Inheritance tutorial, we covered pretty much everything about inheritance. In fact, the concept is simple, and only with practice, you can master its implementation in a good way. With it, you are virtually already writing better code.

What do you think about inheritance? And what about multiple inheritance? Let me know what you think in the comments!

Picture of Alessandro Maggio

Alessandro Maggio

Project manager, critical-thinker, passionate about networking & coding. I believe that time is the most precious resource we have, and that technology can help us not to waste it. I founded ICTShore.com with the same principle: I share what I learn so that you get value from it faster than I did.
Picture of Alessandro Maggio

Alessandro Maggio

Project manager, critical-thinker, passionate about networking & coding. I believe that time is the most precious resource we have, and that technology can help us not to waste it. I founded ICTShore.com with the same principle: I share what I learn so that you get value from it faster than I did.

Alessandro Maggio

2018-06-14T16:30:32+00:00

Unspecified

Python

Unspecified