abc.md
1> **Источник:** https://python-all.ru/3.2/library/abc.html2>3> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.45---67# 27.7. [`abc`](https://python-all.ru/3.2/library/abc.html#module-abc) – Абстрактные базовые классы89**Исходный код:** [Lib/abc.py](https://python-all.ru/src/3.2/Lib/abc.py)1011---1213Этот модуль предоставляет инфраструктуру для определения [*абстрактных базовых классов*](https://python-all.ru/3.2/glossary.html#term-abstract-base-class) (ABC) в Python, как описано в [**PEP 3119**](https://python-all.ru/3.2/library/abc.html); см. PEP, чтобы понять, почему это было добавлено в Python. (См. также [**PEP 3141**](https://python-all.ru/3.2/library/abc.html) и модуль [`numbers`](https://python-all.ru/3.2/library/numbers.html#module-numbers) относительно иерархии типов для чисел на основе ABC.)1415Модуль [`collections`](https://python-all.ru/3.2/library/collections.html#module-collections) содержит несколько конкретных классов, которые наследуются от ABC; их, конечно, можно наследовать далее. Кроме того, модуль [`collections`](https://python-all.ru/3.2/library/collections.html#module-collections) содержит несколько ABC, которые можно использовать для проверки, предоставляет ли класс или экземпляр определённый интерфейс, например, является ли он хешируемым или отображением.1617Этот модуль предоставляет следующий класс:1819#### `class abc.ABCMeta`2021Метакласс для определения абстрактных базовых классов (ABC).2223Use this metaclass to create an ABC. An ABC can be subclassed directly, and then acts as a mix-in class. You can also register unrelated concrete classes (even built-in classes) and unrelated ABCs as “virtual subclasses” – these and their descendants will be considered subclasses of the registering ABC by the built-in [`issubclass()`](https://python-all.ru/3.2/library/functions.html#issubclass) function, but the registering ABC won’t show up in their MRO (Method Resolution Order) nor will method implementations defined by the registering ABC be callable (not even via [`super()`](https://python-all.ru/3.2/library/functions.html#super)). [\[1\]](https://python-all.ru/3.2/library/abc.html#id2)2425Классы, созданные с метаклассом [`ABCMeta`](https://python-all.ru/3.2/library/abc.html#abc.ABCMeta), имеют следующий метод:2627#### `register(subclass)`2829Регистрирует *подкласс* как «виртуальный подкласс» этого ABC. Например:3031```python32from abc import ABCMeta3334class MyABC(metaclass=ABCMeta):35 pass3637MyABC.register(tuple)3839assert issubclass(tuple, MyABC)40assert isinstance((), MyABC)41```4243Также можно переопределить этот метод в абстрактном базовом классе:4445#### `__subclasshook__(subclass)`4647(Должен быть определён как метод класса.)4849Проверяет, считается ли *subclass* подклассом этого ABC. Это означает, что можно дополнительно настроить поведение `issubclass` без необходимости вызывать [`register()`](https://python-all.ru/3.2/library/abc.html#abc.ABCMeta.register) для каждого класса, который требуется считать подклассом ABC. (Этот метод класса вызывается из метода `__subclasscheck__()` ABC.)5051Этот метод должен возвращать `True`, `False` или `NotImplemented`. Если он возвращает `True`, то *subclass* считается подклассом этого ABC. Если он возвращает `False`, то *subclass* не считается подклассом этого ABC, даже если бы обычно им являлся. Если он возвращает `NotImplemented`, проверка на подкласс продолжается обычным механизмом.5253Для демонстрации этих концепций посмотрите на следующий пример определения ABC:5455```python56class Foo:57 def __getitem__(self, index):58 ...59 def __len__(self):60 ...61 def get_iterator(self):62 return iter(self)6364class MyIterable(metaclass=ABCMeta):6566 @abstractmethod67 def __iter__(self):68 while False:69 yield None7071 def get_iterator(self):72 return self.__iter__()7374 @classmethod75 def __subclasshook__(cls, C):76 if cls is MyIterable:77 if any("__iter__" in B.__dict__ for B in C.__mro__):78 return True79 return NotImplemented8081MyIterable.register(Foo)82```8384ABC `MyIterable` определяет стандартный метод итерации, [`__iter__()`](https://python-all.ru/3.2/reference/datamodel.html#object.__iter__), как абстрактный метод. Реализацию, приведённую здесь, можно по-прежнему вызывать из подклассов. Метод `get_iterator()` также является частью абстрактного базового класса `MyIterable`, но его не обязательно переопределять в неабстрактных производных классах.8586Метод класса [`__subclasshook__()`](https://python-all.ru/3.2/library/abc.html#abc.ABCMeta.__subclasshook__), определённый здесь, говорит, что любой класс, имеющий метод [`__iter__()`](https://python-all.ru/3.2/reference/datamodel.html#object.__iter__) в своём `__dict__` (или в атрибуте \_\_dict\_\_ одного из своих базовых классов, доступ к которому осуществляется через список `__mro__`), также считается `MyIterable`.8788Наконец, последняя строка делает `Foo` виртуальным подклассом `MyIterable`, даже если он не определяет метод [`__iter__()`](https://python-all.ru/3.2/reference/datamodel.html#object.__iter__) (он использует старый протокол итерации, основанный на [`__len__()`](https://python-all.ru/3.2/reference/datamodel.html#object.__len__) и [`__getitem__()`](https://python-all.ru/3.2/reference/datamodel.html#object.__getitem__)). Обратите внимание, что это не сделает `get_iterator` доступным как метод `Foo`, поэтому он предоставляется отдельно.8990Он также предоставляет следующие декораторы:9192#### `@abc.abstractmethod`9394Декоратор, указывающий на абстрактные методы.9596Использование этого декоратора требует, чтобы метакласс класса был [`ABCMeta`](https://python-all.ru/3.2/library/abc.html#abc.ABCMeta) или был производным от него. Класс, метакласс которого является производным от [`ABCMeta`](https://python-all.ru/3.2/library/abc.html#abc.ABCMeta), не может быть инстанциирован, если не переопределены все его абстрактные методы и свойства. Абстрактные методы можно вызывать с помощью любого из обычных механизмов вызова через 'super'.9798Динамическое добавление абстрактных методов в класс или попытка изменить статус абстрактности метода или класса после его создания не поддерживаются. [`abstractmethod()`](https://python-all.ru/3.2/library/abc.html#abc.abstractmethod) влияет только на подклассы, производные с помощью обычного наследования; «виртуальные подклассы», зарегистрированные методом ABC `register()`, не затрагиваются.99100Использование:101102```python103class C(metaclass=ABCMeta):104 @abstractmethod105 def my_abstract_method(self, ...):106 ...107```108109> **Примечание**110>111> В отличие от абстрактных методов Java, эти абстрактные методы могут иметь реализацию. Эту реализацию можно вызвать через механизм [`super()`](https://python-all.ru/3.2/library/functions.html#super) из класса, который его переопределяет. Это может быть полезно как конечная точка для вызова super во фреймворке, использующем кооперативное множественное наследование.112113#### `@abc.abstractclassmethod`114115Подкласс встроенного [`classmethod()`](https://python-all.ru/3.2/library/functions.html#classmethod), указывающий на абстрактный классовый метод. В остальном он аналогичен [`abstractmethod()`](https://python-all.ru/3.2/library/abc.html#abc.abstractmethod).116117Использование:118119```python120class C(metaclass=ABCMeta):121 @abstractclassmethod122 def my_abstract_classmethod(cls, ...):123 ...124```125126Новое в версии 3.2.127128#### `@abc.abstractstaticmethod`129130Подкласс встроенного [`staticmethod()`](https://python-all.ru/3.2/library/functions.html#staticmethod), указывающий на абстрактный статический метод. В остальном он аналогичен [`abstractmethod()`](https://python-all.ru/3.2/library/abc.html#abc.abstractmethod).131132Использование:133134```python135class C(metaclass=ABCMeta):136 @abstractstaticmethod137 def my_abstract_staticmethod(...):138 ...139```140141Новое в версии 3.2.142143#### `abc.abstractproperty(fget=None, fset=None, fdel=None, doc=None)`144145Подкласс встроенной функции [`property()`](https://python-all.ru/3.2/library/functions.html#property), обозначающий абстрактное свойство.146147Использование этой функции требует, чтобы метакласс класса был [`ABCMeta`](https://python-all.ru/3.2/library/abc.html#abc.ABCMeta) или был производным от него. Класс, метакласс которого является производным от [`ABCMeta`](https://python-all.ru/3.2/library/abc.html#abc.ABCMeta), не может быть инстанциирован, если не переопределены все его абстрактные методы и свойства. Абстрактные свойства можно вызывать с помощью любого из обычных механизмов вызова через 'super'.148149Использование:150151```python152class C(metaclass=ABCMeta):153 @abstractproperty154 def my_abstract_property(self):155 ...156```157158Это определяет свойство только для чтения; можно также определить абстрактное свойство чтения-записи, используя «длинную» форму объявления свойства:159160```python161class C(metaclass=ABCMeta):162 def getx(self): ...163 def setx(self, value): ...164 x = abstractproperty(getx, setx)165```166167Сноски168169| [\[1\]](https://python-all.ru/3.2/library/abc.html#id1) | Программистам на C++ следует отметить, что концепция виртуального базового класса в Python отличается от C++. |170| --- | --- |171