SoFunction
Updated on 2025-03-04

A brief analysis of the use of interfaces and abstract base classes in Python

touchPythonFriends who were older may have had this experience.PythonAlthough the language also supports object-oriented programming,

However, unlike purely object-oriented languages ​​(e.g.Javaand.NET) So strict and standardized.

As the project gradually grows in size, it becomes increasingly difficult to define and implement the behavior of objects in a clear, maintainable and scalable way.

Two powerful tools for object-oriented programming in Python introduced today:interfaceandAbstract base class

Their English isProtocolsandABC(Abstract Base Classes)。

ProtocolsyesPython3.8It has just begun to be introduced, and some places have also been translated intoprotocol, I feel that it is translated intointerfaceMore familiar.

ABCIt was introduced earlier,Python3It has been improved and optimized later, and now there is not much difference compared with abstract classes in other languages.

1. Interface (Protocols)

Python3.8Start the interface introduced in the type moduleProtocolsThe concept of , which provides a way to define an interface without explicit inheritance.

interfaceProtocolsA set of methods or properties is defined, and as long as an object implements these methods or properties, it is considered to satisfy the interface.

Here is an example to help understandProtocolsIf you have experience in object-oriented programming, you can easily understand this concept.

This example comes from a recently used part of a quantitative trading system that requires a different sourceGet data, and thenanalyze, and finally the analysis results are carried out in different waysOutput

In these three steps (get data, analyze and output),

AssumptionsGet dataThe source of the Internet (API),document(CSV) and database;

The analysis steps are unified; there are many assumptions of output methods, such as email, text messages, etc.

According to this description, useProtocolsThe code for the acquisition data and analysis part of the constructed code is as follows:

The output part is not in mind for the time being

from typing import Protocol


# The interface for inputting dataclass InputData(Protocol):
    def get_data(self) -> str:
        pass


class APIHandler:
    def get_data(self) -> str:
        print("get_data from API")
        return "get data from API"


class CSVHandler:
    def get_data(self) -> str:
        print("get_data from CSV")
        return "get data from CSV"


class SqliteHandler:
    def get_data(self) -> str:
        print("get_data from SQLITE DATABASE")
        return "get data from SQLITE DATABASE"


#Analyze datadef analysis(i: InputData):
    data = i.get_data()

    print("Start the data...")

InputDataInheritedProtocol, which defines the function of the interfaceget_data

As long as it is implementedget_dataofclass,for exampleAPIHandlerCSVHandlerandSqliteHandler, can be used asInputDatatype.

As can be seen from the code, we don't need to use itAPIHandlerGo to inheritInputData, as long as it is implementedInputDataAll the methods in it are OK.

This flexibility ensures the system's scalability, and we can add new data source types without modifying existing code.

Next, we test whether the above code works normally:

if __name__ == "__main__":
    i = APIHandler()
    analysis(i)
    print("\n")

    i = CSVHandler()
    analysis(i)
    print("\n")

    i = SqliteHandler()
    analysis(i)
    print("\n")

Running results:

$   .\protocol_abc.py
get_data from API
Start processing data...

get_data from CSV
Start processing data...

get_data from SQLITE DATABASE
Start processing data...

2. Abstract base class (ABC)

ProtocolVery flexible, but sometimes we need a more structured approach, which is the abstract base class (ABC) is where it comes into play.

ABCIs a tool that enforces consistent behavior by defining strict interfaces that subclasses must implement.

andProtocoldifferent,ABCexplicit inheritance is required, so when we want to explicitly define the hierarchy in our code,ABCIt's a better choice.

Next, implement the example in the previous sectionOutput part, each different output requires a different configuration,

For example, when outputting to email, you need to configure the account information of the email address first, when outputting to text messages, you need to configure the mobile phone information, etc.

Here we useABCto implement the base class of output.

# The abstract base class for outputclass OutputResult(ABC):
    def __init__(self):
        : dict = {}

    @abstractmethod
    def send(self, data: str):
        pass

    @abstractmethod
    def config(self, settings: dict):
        pass


class OutputMail(ABC):
    def send(self, data: str):
        print(f"send {data} to {['name']}")

    def config(self, settings: dict):
         = settings


class OutputMessage(ABC):
    def send(self, data: str):
        print(f"send {data} to {['name']}")

    def config(self, settings: dict):
         = settings

The reason for using abstract base class here is that when output, it is not a simple call.sendJust the method, you also need to configure the output parameters.

So it is better to use abstract base classes with structures.

After adding the output, the analysis function in the previous section is also changed to:

#Analyze datadef analysis(i: InputData, o: OutputResult):
    data = i.get_data()

    print("Start the data...")
    data = ("get data from ", "")

    (data)

The test code is as follows:

if __name__ == "__main__":
    i = APIHandler()
    o = OutputMail()
    ({"name": "aaa@"})
    analysis(i, o)
    print("\n")

    i = CSVHandler()
    o = OutputMessage()
    ({"name": "13911123456"})
    analysis(i, o)
    print("\n")

    i = SqliteHandler()
    o = OutputMail()
    ({"name": "xyz@"})
    analysis(i, o)
    print("\n")

Running results:

$   .\protocol_abc.py
get_data from API
Start processing data...
send API to aaa@

get_data from CSV
Start processing data...
send CSV to 13911123456

get_data from SQLITE DATABASE
Start processing data...
send SQLITE DATABASE to xyz@

3. Choice of both

When we are in actual development design, how should we chooseProtocolandABCWoolen cloth?

actually,ProtocolandABCThe choice between them is not black or white, which usually depends on the background of the project and your goals.

Generally speaking, we prefer to use the following situationsProtocol

  • You are using existing code or want to integrate third-party libraries
  • Flexibility is a priority, you don't want to enforce strict hierarchies
  • Objects from irrelevant class hierarchies require shared behavior

The following situations are preferredABC

  • A system is being designed from scratch and needs to be strengthened
  • The relationship between classes is predictable, and inheritance makes sense
  • Shared features or default behavior reduce duplication and improve consistency

4. Summary

Overall,ProtocolandABCNot two tools that compete with each other, they are complementary.

I useProtocolTransform type safety into legacy systems without the need for massive refactoring.

On the other hand, if I build a system where structure and consistency are crucial from scratch, I useABC

When deciding which one to use, consider the flexibility requirements and long-term goals of the project.

ProtocolProvides flexibility and seamless integration, whileABCHelps build structure and consistency.

By understanding their respective strengths, you can choose the right way to build a robust, maintainable Python system.

This is the article about a brief analysis of the use of interfaces and abstract base classes in Python. For more related contents of Python interfaces and abstract base classes, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!