Абстрактные базовые классы (ABC) - это механизм Python для создания строгих интерфейсов и обеспечения соблюдения контрактов в иерархии классов. Они определены в модуле abc
стандартной библиотеки.
ABC позволяют:
from abc import ABC, abstractmethod
class Shape(ABC):
@abstractmethod
def area(self) -> float:
pass
@abstractmethod
def perimeter(self) -> float:
pass
Помечает метод как абстрактный - подклассы обязаны его реализовать:
class DatabaseConnector(ABC):
@abstractmethod
def connect(self):
pass
@abstractmethod
def execute_query(self, query: str):
pass
Позволяет зарегистрировать класс как виртуальный подкласс без наследования:
class MyDatabase:
def connect(self):
print("Connecting...")
DatabaseConnector.register(MyDatabase) # Теперь issubclass(MyDatabase, DatabaseConnector) == True
ABC можно комбинировать с @property
, @classmethod
и др.:
class Sensor(ABC):
@property
@abstractmethod
def reading(self) -> float:
pass
Попытка создать экземпляр без реализации всех абстрактных методов вызовет TypeError
:
class Circle(Shape):
def __init__(self, radius: float):
self.radius = radius
# TypeError: Can't instantiate abstract class Circle with abstract methods area, perimeter
Определение четкого API для плагинов:
class TextProcessor(ABC):
@abstractmethod
def process(self, text: str) -> str:
pass
class UpperProcessor(TextProcessor):
def process(self, text: str) -> str:
return text.upper()
Python предоставляет полезные ABC в модуле collections.abc
:
from collections.abc import Sequence, MutableMapping
class CustomList(Sequence):
def __init__(self, data):
self.data = list(data)
def __getitem__(self, index):
return self.data[index]
def __len__(self):
return len(self.data)
class Vehicle(ABC):
@property
@abstractmethod
def max_speed(self) -> float:
pass
class Car(Vehicle):
def __init__(self):
self._max_speed = 180.0
@property
def max_speed(self) -> float:
return self._max_speed
class Model(ABC):
@classmethod
@abstractmethod
def from_json(cls, json_data: dict):
pass
ABC полезны для:
Пример с подсветкой (как в VSCode):
from abc import ABC, abstractmethod
from typing import Iterable
class DataExporter(ABC):
@abstractmethod
def export(self, data: Iterable[dict]) -> bool:
"""Экспортирует данные во внешнюю систему"""
pass
@property
@abstractmethod
def format_name(self) -> str:
"""Возвращает название формата экспорта"""
pass