Python Abstract Base Classes

Click to share! ⬇️

Python Abstract Base Classes

Abstract base classes are special types of classes in Python. They allow a programmer to define a base class as a template for other classes to inherit from. The difference between abstract base classes and normal classes in Python is that with abstract base classes you don’t want consumers of your base class to be able to create instances of the base class itself. The abstract base class servers only as a blueprint. Subclasses are the means of providing a concrete implementation of that blueprint. In addition to this, you can enforce the constraint that there are certain methods in the base class that subclasses have to implement.


Simple Class With Inheritance

class Vehicle:
    def __init__(self):
        super().__init__()

    def go_forward(self):
        print('Driving forward.')


class Car(Vehicle):
    def __init__(self):
        super().__init__()


class Truck(Vehicle):
    def __init__(self):
        super().__init__()


vehicle1 = Vehicle()

car1 = Car()
car1.go_forward()

truck1 = Truck()
truck1.go_forward()
Driving forward.
Driving forward.

This code above is a simple Vehicle class and two additional classes, Car and Truck. We want this program to be extensible so that new car or truck types can be added. We can certainly create a program like this without using an abstract base class. In fact, the code above seems to work. When we call the method that was inherited on the car and truck objects, they both drive forward. Notice that we also instantiated a Vehicle object. We don’t really need that since the Car and Truck can do all they need to do without having an instance of Vehicle created. We can change this code up to make use of an abstract base class to accomplish a few things.


Adding Abstract Base Class

To make use of an abstract base class in Python you need to import ABC and abstractmethod as we see here.

from abc import ABC, abstractmethod

Inheriting From Abc Indicates That This Is An Abstract Base Class

The Vehicle class here has a type of <class ‘abc.ABCMeta’>.

from abc import ABC, abstractmethod


class Vehicle(ABC):
    def __init__(self):
        super().__init__()

Declaring A Method As Abstract Requires A Subclass To Implement It

from abc import ABC, abstractmethod


class Vehicle(ABC):
    def __init__(self):
        super().__init__()

    @abstractmethod
    def go_forward(self):
        pass

The syntax above is a bit special. We can see the @abstractmethod decorator which tells Python, this method needs to be implemented by any subclass that inherits from the abstract base class.


Abstract Base Class Can Not Be Instantiated

Since Vehicle has now inherited from ABC, it can no longer be instantiated. If we try, Python will throw an error.

vehicle1 = Vehicle()
Traceback (most recent call last):
  File "C:/python/justhacking/abc.py", line 38, in <module>
    vehicle1 = Vehicle() 
TypeError: Can't instantiate abstract class Vehicle with abstract methods go_forward

Adding A Subclass

Let’s create a Car class example that now inherits from Vehicle. Since we have put some rules in place on the Vehicle class using the ABC module, you’ll see that Python outputs an error if we don’t create the Subclass with the needed attributes or methods.

class Car(Vehicle):
    pass


car1 = Car()
Traceback (most recent call last):
  File "C:/python/justhacking/abc.py", line 38, in <module>
    car1 = Car(True)
TypeError: Can't instantiate abstract class Car with abstract methods go_forward

Python is now enforcing the fact that if we want to have a Subclass of Vehicle, it must implement the go_forward() method. Let’s give it another shot.

class Car(Vehicle):
    def __init__(self, press_accelerator):
        super().__init__()
        self.press_accelerator = press_accelerator

    def go_forward(self):
        if self.press_accelerator:
            print('Driving forward')
        else:
            print('Press the accelerator to drive forward')


car1 = Car(True)
car1.go_forward()
Driving forward

A Second Subclass

We can create a different subclass of Truck that also inherits from the Vehicle abstract base class.

from abc import ABC, abstractmethod


class Vehicle(ABC):
    def __init__(self):
        super().__init__()

    @abstractmethod
    def go_forward(self):
        pass


class Truck(Vehicle):
    def __init__(self, press_accelerator):
        super().__init__()
        self.press_accelerator = press_accelerator

    def go_forward(self):
        if self.press_accelerator:
            print('Driving forward')
        else:
            print('Press the accelerator to drive forward')


truck1 = Truck(False)
truck1.go_forward()

truck2 = Truck(True)
truck2.go_forward()
Press the accelerator to drive forward
Driving forward

Abstract base classes can be a very useful tool for enforcing a set of constraints among the consumers of any given class. Abstract base classes are worth taking the time to experiment with to understand their potential benefits.

  • Abstract classes are classes that are meant to be inherited but avoid implementing specific methods, leaving behind only method signatures that subclasses must implement.
  • Abstract classes are useful for defining and enforcing class abstractions at a high level, similar to the concept of interfaces in typed languages, without the need for method implementation.
  • With the abc module we can prevent child classes from being instantiated when they fail to override abstract class methods of their parents and ancestors.
Click to share! ⬇️