Что такое abstract class в Python?
Абстрактный класс — это класс, который нельзя инстанцировать, пока наследник не реализует все методы, помеченные @abstractmethod. В Python реализуется через модуль abc (наследование от ABC или метакласс ABCMeta).
Что это
Абстрактный класс в Python — это класс, объявленный через модуль abc (наследник abc.ABC или с metaclass=abc.ABCMeta), содержащий один или несколько методов, помеченных декоратором @abstractmethod. Прямое создание экземпляра такого класса (или наследника, не переопределившего все абстрактные методы) бросает TypeError на этапе вызова __init__.
Зачем нужен
- Зафиксировать контракт для семейства классов (например,
Storage,Notifier,PaymentProvider) и получить ошибку при импорте/инстанцировании, а не глубоко в runtime. - Дать частичную реализацию: можно совместить
@abstractmethodс обычными методами и атрибутами, наследники получат готовое поведение и обязаны доопределить только абстрактные части. - Поддержать виртуальное наследование через
register()— пометить чужой класс как наследника без модификации его исходников.
Пример
from abc import ABC, abstractmethod
class Storage(ABC):
@abstractmethod
def save(self, key: str, value: bytes) -> None: ...
@abstractmethod
def load(self, key: str) -> bytes: ...
# Общая реализация — наследники получат её бесплатно
def save_text(self, key: str, text: str) -> None:
self.save(key, text.encode("utf-8"))
class MemoryStorage(Storage):
def __init__(self) -> None:
self._data: dict[str, bytes] = {}
def save(self, key: str, value: bytes) -> None:
self._data[key] = value
def load(self, key: str) -> bytes:
return self._data[key]
Storage() # TypeError: Can't instantiate abstract class Storage
MemoryStorage() # OK — все abstractmethod переопределены
ABC vs Protocol
abc.ABC — runtime-механизм, требует явного наследования и проверяет реализацию при инстанцировании. typing.Protocol — structural typing, проверяется статически (mypy/pyright) и не требует наследования: достаточно, чтобы у объекта были нужные методы. Используйте ABC, когда важна общая реализация и runtime-проверка; Protocol — когда нужен только тип-контракт для duck typing.
Сопутствующие декораторы
@abstractmethod— обязательный метод.@property+@abstractmethod— абстрактное свойство (порядок:@propertyсверху).@classmethod/@staticmethod+@abstractmethod— абстрактные фабрики.
Подводные камни
- Декоратор
@abstractmethodсам по себе не работает — класс должен наследоваться отABCили использоватьABCMeta, иначе экземпляр создастся без ошибки. - Старая идиома
class Foo(metaclass=ABCMeta)ломает множественное наследование, если другой родитель тоже задаёт метакласс — удобнее наследоваться отABC. - Класть в абстрактный класс слишком много реализации — получите жёсткую иерархию вместо контракта.
ABC.register(cls)делаетisinstance-проверку истинной, но не проверяет, что уclsдействительно есть нужные методы — это ответственность разработчика.
Common mistakes
- Не знать abc.ABC.
- Считать abstractmethod только документацией.
- Не отличать ABC от Protocol.
What the interviewer is testing
- Показывает ABC и abstractmethod.
- Объясняет TypeError при инстанцировании.
- Знает альтернативу Protocol.