Inheritance in Python

Learn when to opt for inheritance in Python and antipatterns for inheritance.

In object-oriented software design, there are often discussions on to how to address problems by using the main ideas of the paradigm (polymorphism, inheritance, and encapsulation). Probably the most commonly used of these ideas is inheritance—developers often start by creating a class hierarchy with the classes they are going to need and decide the methods each one should implement.

While inheritance is a powerful concept, it does come with its perils. The main one is that every time we extend a base class, we are creating a new one that is tightly coupled with the parent. As we have already discussed, coupling is one of the things we want to reduce to a minimum when designing software.

One of the main scenarios developers relate inheritance with is code reuse. While we should always embrace code reuse, it is not a good idea to force our design to use inheritance to reuse code just because we get the methods from the parent class for free. The proper way to reuse code is to have highly cohesive objects that can be easily composed and that could work on multiple contexts.

When inheritance is a good decision

We have to be careful when creating a derived class because this is a double-edged sword—on the one hand, it has the advantage that we get all the code of the methods from the parent class for free, but on the other hand, we are carrying all of them to a new class, meaning that we might be placing too much functionality in a new definition.

When creating a new subclass, we have to think if it is actually going to use all of the methods it has just inherited, as a heuristic to see whether the class is correctly defined. If instead, we find out that we don't need most of the methods, and have to override or replace them, this is a design mistake that could be caused by a number of reasons:

  • The superclass is vaguely defined and contains too much responsibility instead of a well-defined interface.

  • The subclass is not a proper specialization of the superclass it is trying to extend.

A good case for using inheritance is the type of situation when there's a class that defines certain components with its behavior that are defined by the interface of this class (its public methods and attributes), and then we need to specialize this class in order to create objects that do the same but with something else added, or with some particular parts of its behavior changed.

Get hands-on with 1200+ tech skills courses.