abc — Абстрактные базовые классы
Впервые в версии 2.6.
Исходный код: Lib/abc.py
Этот модуль предоставляет инфраструктуру для определения абстрактных базовых классов (ABC) в Python, как описано в PEP 3119; см. PEP для объяснения причины добавления этой функциональности в Python. (См. также PEP 3141 и numbers модуль по иерархии типов чисел на основе ABC.)
Модуль collections содержит некоторые конкретные классы, производные от ABC; их, конечно, можно дополнительно наследовать. Кроме того, модуль collections содержит некоторые ABC, которые можно использовать для проверки, предоставляет ли класс или экземпляр определённый интерфейс, например, является ли он хешируемым или является ли он отображением.
Этот модуль предоставляет следующий класс:
-
class abc.ABCMeta -
Метакласс для определения абстрактных базовых классов (ABC).
Используйте этот метакласс для создания ABC. ABC можно наследовать напрямую, и тогда он действует как миксин-класс. Вы также можете регистрировать не связанные конкретные классы (даже встроенные классы) и не связанные ABC как «виртуальные подклассы» — эти подклассы и их потомки будут считаться подклассами регистрируемого ABC функцией
issubclass(), но регистрируемый ABC не отобразится в порядке разрешения методов (MRO) и реализации методов, определённые регистрируемым ABC, не будут вызываемыми (даже черезsuper()). 1Классы, созданные с метаклассом
ABCMeta, имеют следующий метод:-
register(subclass) -
Регистрирует подкласс как «виртуальный подкласс» этого ABC. Например:
from abc import ABCMeta class MyABC: __metaclass__ = ABCMeta MyABC.register(tuple) assert issubclass(tuple, MyABC) assert isinstance((), MyABC)
Вы также можете переопределить этот метод в абстрактном базовом классе:
-
__subclasshook__(subclass) -
(Должен быть определён как метод класса.)
Проверяет, считается ли подкласс подклассом этого ABC. Это означает, что вы можете настроить поведение
issubclassдальше без необходимости вызоваregister()для каждого класса, который вы хотите рассматривать как подкласс ABC. (Этот метод класса вызывается из метода__subclasscheck__()ABC.)Этот метод должен возвращать
True,FalseилиNotImplemented. Если он возвращаетTrue, то подкласс считается подклассом этого ABC. Если он возвращаетFalse, то подкласс не считается подклассом этого ABC, даже если он обычно таковым является. Если он возвращаетNotImplemented, проверка подкласса продолжается стандартным механизмом.
Для демонстрации этих концепций посмотрите этот пример определения ABC:
class Foo(object): def __getitem__(self, index): ... def __len__(self): ... def get_iterator(self): return iter(self) class MyIterable: __metaclass__ = ABCMeta @abstractmethod def __iter__(self): while False: yield None def get_iterator(self): return self.__iter__() @classmethod def __subclasshook__(cls, C): if cls is MyIterable: if any("__iter__" in B.__dict__ for B in C.__mro__): return True return NotImplemented MyIterable.register(Foo)ABC
MyIterableопределяет стандартный метод итерируемости,__iter__(), как абстрактный метод. Предоставленная здесь реализация по-прежнему может вызываться из подклассов. Методget_iterator()также является частью абстрактного базового классаMyIterable, но он не должен переопределяться в производных классах, не являющихся абстрактными.Метод класса
__subclasshook__(), определённый здесь, говорит, что любой класс, имеющий метод__iter__()в своём__dict__(или в одном из своих базовых классов, доступном через список__mro__), также считаетсяMyIterable.Наконец, последняя строка делает
Fooвиртуальным подклассомMyIterable, даже если он не определяет метод__iter__()(он использует протокол итерируемости старой формы, определённый в терминах__len__()и__getitem__()). Обратите внимание, что это не сделаетget_iteratorдоступным в качестве методаFoo, поэтому он предоставляется отдельно. -
Он также предоставляет следующие декораторы:
-
abc.abstractmethod(function) -
Декоратор, указывающий абстрактные методы.
Использование этого декоратора требует, чтобы метакласс класса был
ABCMetaили был от него производным. Класс, имеющий метакласс, производный отABCMeta, не может быть экземпляризован, если не все его абстрактные методы и свойства не будут переопределены. К абстрактным методам можно обращаться с помощью любых обычных механизмов вызова «super».Динамическое добавление абстрактных методов в класс или попытка изменить статус абстракции метода или класса после его создания не поддерживаются. Декоратор
abstractmethod()влияет только на подклассы, полученные с помощью обычного наследования; «виртуальные подклассы», зарегистрированные с помощью методаregister()ABC, не затрагиваются.Использование:
class C: __metaclass__ = ABCMeta @abstractmethod def my_abstract_method(self, ...): ...Примечание
В отличие от абстрактных методов Java, эти абстрактные методы могут иметь реализацию. К этой реализации можно обратиться с помощью механизма
super()из класса, который её переопределяет. Это может быть полезно в качестве конечной точки для вызова super в фреймворке, использующем кооперативное множественное наследование.
-
abc.abstractproperty([fget[, fset[, fdel[, doc]]]]) -
Подкласс встроенной функции
property(), указывающий абстрактное свойство.Использование этой функции требует, чтобы метакласс класса был
ABCMetaили был от него производным. Класс, имеющий метакласс, производный отABCMeta, не может быть экземпляризован, если не все его абстрактные методы и свойства не будут переопределены. К абстрактным свойствам можно обращаться с помощью любых обычных механизмов вызова «super».Использование:
class C: __metaclass__ = ABCMeta @abstractproperty def my_abstract_property(self): ...Это определяет только для чтения свойство; вы также можете определить свойство только для чтения и записи с помощью «длинной» формы объявления свойства:
class C: __metaclass__ = ABCMeta def getx(self): ... def setx(self, value): ... x = abstractproperty(getx, setx)
Сноски
-
1 -
Программисты C++ должны заметить, что концепция виртуального базового класса в Python не такая же, как в C++.
© 2001–2020 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/2.7/library/abc.html