Spec-Zone.ru › Python 2.7

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

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API