Abstract base classes, implemented through the Python abc module, allow you to write cleaner, safer code. But what are abstract classes and when do you need them? In this tutorial, you’ll learn what abstract base classes are in Python, how to use the Python abc module, and how to use abstractmethod and abstract properties.
In a nutshell, abstract base classes allow you to implement rules around subclasses. This allows you to define methods that a subclass must have. Similarly, it allows you to define what parameters a subclass must have.
By the end of this tutorial, you’ll have learned the following:
- How to create abstract base classes in Python using the abc module
- How to enforce methods in subclasses using the abstractmethod decorators
- How to force and use parameters when using methods in subclasses
- How to enforce properties when subclassing data in Python using the abc module
Table of Contents
Understanding Abstract Base Classes with Python abc
Python implements abstract classes through the abc
library. But, what are abstract classes, really? Abstract classes are classes that contain one or more abstract methods. These methods are declared but not implemented. In fact, you don’t instantiate an abstract class, but use a subclass to provide the details for implementation via its abstract methods.
All of this may seem like a lot – and it is a bit abstract. For me, the simplest way to understand this is to think of abstract classes as being a framework of what a subclass must have.
Let’s walk through an example. Imagine that we want to define a set of classes for employees, specifically for managers, supervisors, and staff. For these employees, all staff should be able to arrive at work. Let’s see how we might define what this looks like:
# Implementing Classes Without Abstract Base Classes
class Manager:
def arrive_at_work(self):
print("Arrived at work")
class Supervisor:
def get_to_work(self):
print("Got to work")
class Staff:
def show_up(self):
print("Showed up")
All of these classes have methods that, functionally, do the same thing – have the employee get to work. However, if we want to actually have the employee object show up at work, we need to use three different implementations for the same thing.
This is where abstract base classes come into play. We can enforce what methods are required when subclassing by using the Python abc module. For example, if we know that each employee needs to get to work, we can define an abstract method to accomplish this.
Now that we’ve developed a good case for using abstract classes in Python, let’s dive into how to do this using the Python abc module.
How to Use abstractmethod With Python abc
In order to create abstract classes in Python, we can use the built-in abc module. The module provides both the ABC
class and the abstractmethod
decorator. Let’s dive into how to create an abstract base class:
# Implementing an Abstract Base Class
from abc import ABC, abstractmethod
class Employee(ABC):
@abstractmethod
def arrive_at_work(self):
pass
We can see that we now have a class Employee
, which inherits from the ABC
class itself. The class has only a single method, which is decorated using the @abstractmethod
decorator. The method itself doesn’t do anything but accepts the self
keyword as an argument. This part is important: the method shouldn’t do anything except for exist.
Now when we create subclasses of the Employee
class, these classes will need to have a method named .arrive_at_work()
. Let’s see what happens when we create a subclass with a different method:
# Implementing an Abstract Base Class Without Correct Method
from abc import ABC, abstractmethod
class Employee(ABC):
@abstractmethod
def arrive_at_work(self):
pass
class Manager(Employee):
def show_up(self):
print("I'm here!")
nik = Manager()
# Returns:
# TypeError: Can't instantiate abstract class Manager with abstract method arrive_at_work
Instantiating our Manager
class raises a TypeError
since we don’t have a .arrive_at_work()
method. Let’s see how we can resolve this issue:
# Implementing an Abstract Base Class Correctly
from abc import ABC, abstractmethod
class Employee(ABC):
@abstractmethod
def arrive_at_work(self):
pass
class Manager(Employee):
def arrive_at_work(self):
print("Arriving at datagy.io headquarters!")
nik = Manager()
When we run the code above, no error is raised. This is because we have the correctly named method.
Remember from earlier in the tutorial that the implementation of the abstract method is up to the subclass itself. Because of this, we can have different implementations of these methods which do different things – as long as they have the correct names. Let’s see what this looks like:
# Implementing Different Methods for Classes
from abc import ABC, abstractmethod
class Employee(ABC):
@abstractmethod
def arrive_at_work(self):
pass
class Manager(Employee):
def arrive_at_work(self):
print("Arriving at datagy.io headquarters!")
class Supervisor(Employee):
def arrive_at_work(self):
print("Reporting for duty at datagy.io!")
nik = Manager()
katie = Supervisor()
We can see in the example above that the code runs fine. This is because both subclasses have the correct name – even if their implementations differ.
In the following section, you’ll learn how to add parameters to an abstractmethod
and how to enforce that they exist in any subclasses.
How to Add Parameters to an abstractmethod in Python abc
What’s great about the abstractmethod
decorator is that we can even require a method to have one or more parameters. This allows you to ensure that any method that exists in the subclass has the required parameters.
For example, if you needed the .arrive_at_work()
method to have a time passed in, then you can do this using the abstractmethod
decorator. Let’s see what this looks like:
# Adding Parameters to Methods in Abstract Base Classes
from abc import ABC, abstractmethod
class Employee(ABC):
@abstractmethod
def arrive_at_work(self, arrival_time):
pass
class Manager(Employee):
def arrive_at_work(self, arrival_time):
print(f"Arriving at datagy.io headquarters at {arrival_time}!")
class Supervisor(Employee):
def arrive_at_work(self, arrival_time, location):
print(
f"Reporting at datagy.io at {arrival_time} at the {location} office!")
nik = Manager()
nik.arrive_at_work(8)
katie = Supervisor()
katie.arrive_at_work(9, 'Toronto')
# Returns:
# Arriving at datagy.io headquarters at 8!
# Reporting at datagy.io at 9 at the Toronto office!
In the code block above, we use the ABC class to create an abstract base class. The method in the class has an additional parameter, arrival_time
. Both subclasses have this parameter and are required to have the parameter.
What’s interesting is that the Supervisor
subclass actually has an additional parameter. The subclass only requires the parameters defined in the abstract class itself, but can also have additional parameters.
How to Add Properties to Abstract Base Classes in Python
In this section, you’ll learn how to add properties to abstract base classes. This allows you to ensure that certain properties are set when creating an abstract base class. This process is a bit more involved, so let’s take a look at an example.
# Adding Properties to Abstract Base Classes
from abc import ABC, abstractmethod
class Employee(ABC):
@abstractmethod
def __init__(self, name):
self._name = name
@property
@abstractmethod
def name(self):
pass
@name.setter
@abstractmethod
def name(self, value):
pass
class Manager(Employee):
def __init__(self, name):
self._name = name
@property
def name(self):
return self._name
@name.setter
def name(self, value):
self._name = value
nik = Manager('Nik')
print(nik.name)
# Returns: Nik
In the example above, we use the @property
decorator to ensure that items are labeled as properties. We also need to provide setter methods in order to make sure that they work. Notice that we implement the property before we define the setter.
Then, in the subclass, we follow a similar method of defining these items. As long as our properties and methods have the correct names, the subclass will inherit appropriately.
Conclusion
In this tutorial, you learned how to use the Python abc module to create abstract base classes, which act as blueprints for additional subclasses. You first learned why the concept of abstract classing is important. Then, you learned how to use the ABC class from the abc module to create an abstract class framework.
From there, you learned how to define abstract methods using the abstractmethod decorator. You also learned how to require certain parameters for subclass methods. Finally, you also learned how to set properties for any subclasses of abstract base classes.
Additional Resources
To learn more about related topics, check out the resources below: