abc.md
1> **Источник:** https://python-all.ru/2.7/library/abc.html2>3> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.45---67# 28.8. [`abc`](https://python-all.ru/2.7/library/abc.html#module-abc) – Абстрактные базовые классы89Новое в версии 2.6.1011**Исходный код:** [Lib/abc.py](https://python-all.ru/src/2.7/Lib/abc.py)1213---1415Этот модуль предоставляет инфраструктуру для определения [абстрактных базовых классов](https://python-all.ru/2.7/glossary.html#term-abstract-base-class) (ABC) в Python, как описано в [**PEP 3119**](https://python-all.ru/2.7/library/abc.html); см. PEP, чтобы узнать, почему это было добавлено в Python. (См. также [**PEP 3141**](https://python-all.ru/2.7/library/abc.html) и модуль [`numbers`](https://python-all.ru/2.7/library/numbers.html#module-numbers), касающийся иерархии типов для чисел на основе ABC.)1617Модуль [`collections`](https://python-all.ru/2.7/library/collections.html#module-collections) содержит несколько конкретных классов, которые наследуются от ABC; их, конечно, можно наследовать дальше. Кроме того, модуль [`collections`](https://python-all.ru/2.7/library/collections.html#module-collections) содержит несколько ABC, которые можно использовать для проверки того, предоставляет ли класс или экземпляр определённый интерфейс, например, является ли он хешируемым или отображением.1819Этот модуль предоставляет следующий класс:2021#### `class abc.ABCMeta`2223Метакласс для определения абстрактных базовых классов (ABC).2425Используйте этот метакласс для создания ABC. ABC может быть напрямую унаследован, а затем действует как примесь (mix-in). Также можно регистрировать несвязанные конкретные классы (даже встроенные классы) и несвязанные ABC как «виртуальные подклассы» – они и их потомки будут считаться подклассами регистрирующего ABC встроенной функцией [`issubclass()`](https://python-all.ru/2.7/library/functions.html#issubclass), но регистрирующий ABC не появится в их MRO (порядке разрешения методов), и реализации методов, определённые регистрирующим ABC, не будут вызываемыми (даже через [`super()`](https://python-all.ru/2.7/library/functions.html#super)). [1](https://python-all.ru/2.7/library/abc.html#id2)2627Классы, созданные с метаклассом [`ABCMeta`](https://python-all.ru/2.7/library/abc.html#abc.ABCMeta), имеют следующий метод:2829#### `register(subclass)`3031Регистрирует *подкласс* как «виртуальный подкласс» этого ABC. Например:3233```python34from abc import ABCMeta3536class MyABC:37 __metaclass__ = ABCMeta3839MyABC.register(tuple)4041assert issubclass(tuple, MyABC)42assert isinstance((), MyABC)43```4445Также можно переопределить этот метод в абстрактном базовом классе:4647#### `__subclasshook__(subclass)`4849(Должен быть определён как метод класса.)5051Проверяет, считается ли *подкласс* подклассом этого ABC. Это означает, что можно дополнительно настраивать поведение `issubclass` без необходимости вызывать [`register()`](https://python-all.ru/2.7/library/abc.html#abc.ABCMeta.register) для каждого класса, который требуется считать подклассом ABC. (Этот метод класса вызывается из метода `__subclasscheck__()` ABC.)5253Этот метод должен возвращать `True`, `False` или `NotImplemented`. Если он возвращает `True`, то *подкласс* считается подклассом этого ABC. Если он возвращает `False`, то *подкласс* не считается подклассом этого ABC, даже если бы он обычно им был. Если он возвращает `NotImplemented`, проверка на подкласс продолжается обычным механизмом.5455Для демонстрации этих концепций посмотрите на следующий пример определения ABC:5657```python58class Foo(object):59 def __getitem__(self, index):60 ...61 def __len__(self):62 ...63 def get_iterator(self):64 return iter(self)6566class MyIterable:67 __metaclass__ = ABCMeta6869 @abstractmethod70 def __iter__(self):71 while False:72 yield None7374 def get_iterator(self):75 return self.__iter__()7677 @classmethod78 def __subclasshook__(cls, C):79 if cls is MyIterable:80 if any("__iter__" in B.__dict__ for B in C.__mro__):81 return True82 return NotImplemented8384MyIterable.register(Foo)85```8687ABC `MyIterable` определяет стандартный метод итерируемых объектов, [`__iter__()`](https://python-all.ru/2.7/library/stdtypes.html#iterator.__iter__), как абстрактный метод. Приведённую здесь реализацию всё ещё можно вызывать из подклассов. Метод `get_iterator()` также является частью абстрактного базового класса `MyIterable`, но его не обязательно переопределять в неабстрактных производных классах.8889The [`__subclasshook__()`](https://python-all.ru/2.7/library/abc.html#abc.ABCMeta.__subclasshook__) class method defined here says that any class that has an [`__iter__()`](https://python-all.ru/2.7/library/stdtypes.html#iterator.__iter__) method in its [`__dict__`](https://python-all.ru/2.7/library/stdtypes.html#object.__dict__) (or in that of one of its base classes, accessed via the [`__mro__`](https://python-all.ru/2.7/library/stdtypes.html#class.__mro__) list) is considered a `MyIterable` too.9091Наконец, последняя строка делает `Foo` виртуальным подклассом `MyIterable`, даже если он не определяет метод [`__iter__()`](https://python-all.ru/2.7/library/stdtypes.html#iterator.__iter__) (он использует старый протокол итерирования, определённый через [`__len__()`](https://python-all.ru/2.7/reference/datamodel.html#object.__len__) и [`__getitem__()`](https://python-all.ru/2.7/reference/datamodel.html#object.__getitem__)). Обратите внимание, что это не сделает `get_iterator` доступным в качестве метода `Foo`, поэтому он предоставляется отдельно.9293Он также предоставляет следующие декораторы:9495#### `abc.abstractmethod(function)`9697Декоратор, указывающий на абстрактные методы.9899Использование этого декоратора требует, чтобы метакласс класса был [`ABCMeta`](https://python-all.ru/2.7/library/abc.html#abc.ABCMeta) или был производным от него. Класс, метакласс которого является производным от [`ABCMeta`](https://python-all.ru/2.7/library/abc.html#abc.ABCMeta), не может быть инстанциирован, пока все его абстрактные методы и свойства не будут переопределены. Абстрактные методы можно вызывать с помощью любого из обычных механизмов вызова ‘super’.100101Динамическое добавление абстрактных методов в класс или попытка изменить статус абстракции метода или класса после его создания не поддерживаются. [`abstractmethod()`](https://python-all.ru/2.7/library/abc.html#abc.abstractmethod) влияет только на подклассы, полученные с помощью обычного наследования; «виртуальные подклассы», зарегистрированные с помощью метода `register()` ABC, не затрагиваются.102103Использование:104105```python106class C:107 __metaclass__ = ABCMeta108 @abstractmethod109 def my_abstract_method(self, ...):110 ...111```112113> **Примечание**114>115> В отличие от абстрактных методов Java, эти абстрактные методы могут иметь реализацию. Эту реализацию можно вызвать через механизм [`super()`](https://python-all.ru/2.7/library/functions.html#super) из класса, который её переопределяет. Это может быть полезно как конечная точка для вызова super в среде, использующей кооперативное множественное наследование.116117#### `abc.abstractproperty([fget[, fset[, fdel[, doc]]]])`118119Подкласс встроенного [`property()`](https://python-all.ru/2.7/library/functions.html#property), указывающий на абстрактное свойство.120121Использование этой функции требует, чтобы метакласс класса был [`ABCMeta`](https://python-all.ru/2.7/library/abc.html#abc.ABCMeta) или был производным от него. Класс, метакласс которого является производным от [`ABCMeta`](https://python-all.ru/2.7/library/abc.html#abc.ABCMeta), не может быть инстанциирован, пока все его абстрактные методы и свойства не будут переопределены. Абстрактные свойства можно вызывать с помощью любого из обычных механизмов вызова ‘super’.122123Использование:124125```python126class C:127 __metaclass__ = ABCMeta128 @abstractproperty129 def my_abstract_property(self):130 ...131```132133Это определяет свойство только для чтения; можно также определить абстрактное свойство чтения-записи, используя «длинную» форму объявления свойства:134135```python136class C:137 __metaclass__ = ABCMeta138 def getx(self): ...139 def setx(self, value): ...140 x = abstractproperty(getx, setx)141```142143Сноски144145**[1](https://python-all.ru/2.7/library/abc.html#id1)**146147Программистам на C++ следует отметить, что концепция виртуального базового класса в Python отличается от C++.148