Does Python Have Interfaces?
Python claims to be a multi-paradigm language with rich OOP capabilities. It has a lot of features that are a must-have for a modern object-oriented programming language - but is interface on of these? Are there interfaces in Python?
Python does not have interfaces, but the same functionality can be achieved with the help of abstract base classes and multiple inheritance. The reason for not having interfaces is that Python does not use static typing, so there’s no compile-time type checking.
In this article we’ll look into what duck typing is, how to use Python’s abstract base classes, and what other options you have in Python regarding interfaces.
What Is An Interface?
In Object Oriented Programming an interface is a construct that can be used to enforce a set of properties or methods on a class that implements the interface. It is similar to a parent class, with the difference that it is completely abstract - it defines the signature of the required methods, but provides no default implementation.
Why Python Does Not Support Interfaces?
In statically typed languages like Java or C#, type checking happens at compile time. Python however, is a dynamically typed language, which means that there are no compile-time guarantees for type-safety, so an interface would not be that useful.
Static Typing vs Duck Typing
In statically typed languages you have to explicitly define the type of your variables, and the compiler will throw an error if you try to assign a different type of object to a variable.
In Python you do not have to do that, the type system is based on the following motto:
If it walks like a duck and it quacks like a duck, then it must be a duck.
Which means, that Python interpreter does not need to know the type of an object - so it is not required explicitly declare it. If the object has the necessary methods (implicitly implements the interface) - it is “good enough” for Python. The downside is that typechecking happens only at runtime.
Proposal For Python Interfaces
In fact, there was an attempt to introduce the interface
keyword to Python. In 2001, Michel Pelletier created PEP-245, with proposed a syntax and a behaviour for interfaces. After 5 years it got refused by Guido van Rossum, with the following note:
While at some point I expect that Python will have interfaces, it would be naive to expect it to resemble the syntax in this PEP. Also, PEP 246 is being rejected in favor of something completely different; interfaces won’t play a role in adaptation or whatever will replace it.
Defining/Using Interfaces in Python
So what does Python have instead of interfaces? If you want to use interface-like constructs, you should look into the abc package.
Abstract Base Classes
The abc
package contains some handy tools for defining Abstract Base Classes. ABCs can have one or more abstract method or property. The methods/properties must be overridden by any inheriting class, otherwise it the class can not be instantiated.
Let’s see an example:
from abc import ABC, abstractmethod
class Animal(ABC):
@abstractmethod
def make_a_noise():
pass
If we define child class without overriding the abstract method:
class Dog(Animal):
pass
The Python interpreter won’t let us instantiate it:
fluffy = Dog()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: Can't instantiate abstract class Dog with abstract methods make_a_noise
Let’s fix that:
class Dog(Animal):
def make_a_noise():
return "bark"
Note: unlike most other languages Python’s abstract methods can have an implementation (to be called via super()
). So this is completely valid:
from abc import ABC, abstractmethod
class Animal(ABC):
@abstractmethod
def make_a_noise():
return None
class Fish(Animal):
def make_a_noise():
return super().make_a_noise()
If you don’t want your method to have a default implementation, you can leave the function body empty (just write a single pass
statement) or raise a NotImplementedError
Multiple Inheritance
In Python any class can have multiple parent classes - which means that a class can inherit from multiple abstract base classes (the equivalent of implementing multiple interfaces).
A simplistic example:
from abc import ABC, abstractmethod
class Animal(ABC):
@abstractmethod
def make_a_noise():
pass
class Pet(ABC):
@abstractmethod
def play():
pass
class Dog(Animal, Pet):
def make_a_noise():
return "bark"
def play():
return "fetch a ball"
Alternative Options For Python Interfaces
The ABC
is a clean, flexible and pythonic way of simulating interfaces. However, if you are looking for an alternative that is a bit more strict, there is a 3rd party package called interface
:
The interface
Package
The interface package provides an alternative interface implementation for Python. The syntax is similar to that of Java, and the behaviour is also closer to it, as interface implementations are checked when the implementing class is loaded - not when the class is instantiated.
To install the package, you can use pip
:
pip install python-interface
The previous example with interface
s instead of ABC
s:
from interface import implements, Interface
class Animal(Interface):
def make_a_noise(self):
pass
class Dog(implements(Animal)):
def make_a_noise(self, x):
return "bark"
Summary
Python does not have interfaces, as they are not really need as a separate language construct - according to Python’s philosophy, “there should one obvious way to do it”. In Python you can use Abstract Base Classes in place of interfaces - multiple inheritence, and dynamic typing makes them even more flexible, at the price of sacrificing the safety of compile-time type-checking.