# `abc` — Abstract Base Classes

Вихідний код: Lib/abc.py

Цей модуль забезпечує інфраструктуру для визначення абстрактних базових класів (ABC) у Python, як описано в PEP 3119; див. PEP, чому це було додано до Python. (Див. також PEP 3141 і модуль `numbers` щодо ієрархії типів для чисел на основі ABC.)

The `collections` module has some concrete classes that derive from ABCs; these can, of course, be further derived. In addition, the `collections.abc` submodule has some ABCs that can be used to test whether a class or instance provides a particular interface, for example, if it is hashable or if it is a mapping.

Цей модуль надає метаклас `ABCMeta` для визначення ABC і допоміжний клас `ABC` для альтернативного визначення ABC через успадкування:

class abc.ABC

  A helper class that has `ABCMeta` as its metaclass. With this class, an abstract base class can be created by simply deriving from `ABC` avoiding sometimes confusing metaclass usage, for example:

      from abc import ABC

      class MyABC(ABC):
          pass

  Note that the type of `ABC` is still `ABCMeta`, therefore inheriting from `ABC` requires the usual precautions regarding metaclass usage, as multiple inheritance may lead to metaclass conflicts. One may also define an abstract base class by passing the metaclass keyword and using `ABCMeta` directly, for example:

      from abc import ABCMeta

      class MyABC(metaclass=ABCMeta):
          pass

  Нове в версії 3.4.

class abc.ABCMeta

  Метаклас для визначення абстрактних базових класів (ABC).

  Використовуйте цей метаклас для створення ABC. ABC може бути безпосередньо підкласом, а потім діяти як змішаний клас. Ви також можете зареєструвати непов’язані конкретні класи (навіть вбудовані) і непов’язані ABC як «віртуальні підкласи» — ці та їхні нащадки вважатимуться підкласами реєструючого ABC вбудованою функцією `issubclass()`, але реєструючий ABC не відображатиметься в їхньому MRO (Method Resolution Order), а також реалізації методів, визначені реєструючим ABC, не можна буде викликати (навіть через `super()`). [1]

  Classes created with a metaclass of `ABCMeta` have the following method:

  register(subclass)

    Зареєструйте підклас як «віртуальний підклас» цього ABC. Наприклад:

        from abc import ABC

        class MyABC(ABC):
            pass

        MyABC.register(tuple)

        assert issubclass(tuple, MyABC)
        assert isinstance((), MyABC)

    Змінено в версії 3.3: Повертає зареєстрований підклас, щоб дозволити використання як декоратор класу.

    Змінено в версії 3.4: To detect calls to `register()`, you can use the `get_cache_token()` function.

  Ви також можете перевизначити цей метод в абстрактному базовому класі:

  __subclasshook__(subclass)

    (Повинен бути визначений як метод класу.)

    Check whether subclass is considered a subclass of this ABC. This means that you can customize the behavior of `issubclass()` further without the need to call `register()` on every class you want to consider a subclass of the ABC. (This class method is called from the `__subclasscheck__()` method of the ABC.)

    This method should return `True`, `False` or `NotImplemented`. If it returns `True`, the subclass is considered a subclass of this ABC. If it returns `False`, the subclass is not considered a subclass of this ABC, even if it would normally be one. If it returns `NotImplemented`, the subclass check is continued with the usual mechanism.

  Для демонстрації цих концепцій подивіться на цей приклад визначення ABC:

      class Foo:
          def __getitem__(self, index):
              ...
          def __len__(self):
              ...
          def get_iterator(self):
              return iter(self)

      class MyIterable(ABC):

          @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)

  The ABC `MyIterable` defines the standard iterable method, `__iter__()`, as an abstract method. The implementation given here can still be called from subclasses. The `get_iterator()` method is also part of the `MyIterable` abstract base class, but it does not have to be overridden in non-abstract derived classes.

  The `__subclasshook__()` class method defined here says that any class that has an `__iter__()` method in its `__dict__` (or in that of one of its base classes, accessed via the `__mro__` list) is considered a `MyIterable` too.

  Finally, the last line makes `Foo` a virtual subclass of `MyIterable`, even though it does not define an `__iter__()` method (it uses the old-style iterable protocol, defined in terms of `__len__()` and `__getitem__()`). Note that this will not make `get_iterator` available as a method of `Foo`, so it is provided separately.

The `abc` module also provides the following decorator:

@abc.abstractmethod

  Декоратор, що вказує на абстрактні методи.

  Using this decorator requires that the class’s metaclass is `ABCMeta` or is derived from it. A class that has a metaclass derived from `ABCMeta` cannot be instantiated unless all of its abstract methods and properties are overridden. The abstract methods can be called using any of the normal „super“ call mechanisms. `abstractmethod()` may be used to declare abstract methods for properties and descriptors.

  Dynamically adding abstract methods to a class, or attempting to modify the abstraction status of a method or class once it is created, are only supported using the `update_abstractmethods()` function. The `abstractmethod()` only affects subclasses derived using regular inheritance; «virtual subclasses» registered with the ABC’s `register()` method are not affected.

  When `abstractmethod()` is applied in combination with other method descriptors, it should be applied as the innermost decorator, as shown in the following usage examples:

      class C(ABC):
          @abstractmethod
          def my_abstract_method(self, arg1):
              ...
          @classmethod
          @abstractmethod
          def my_abstract_classmethod(cls, arg2):
              ...
          @staticmethod
          @abstractmethod
          def my_abstract_staticmethod(arg3):
              ...

          @property
          @abstractmethod
          def my_abstract_property(self):
              ...
          @my_abstract_property.setter
          @abstractmethod
          def my_abstract_property(self, val):
              ...

          @abstractmethod
          def _get_x(self):
              ...
          @abstractmethod
          def _set_x(self, val):
              ...
          x = property(_get_x, _set_x)

  In order to correctly interoperate with the abstract base class machinery, the descriptor must identify itself as abstract using `__isabstractmethod__`. In general, this attribute should be `True` if any of the methods used to compose the descriptor are abstract. For example, Python’s built-in `property` does the equivalent of:

      class Descriptor:
          ...
          @property
          def __isabstractmethod__(self):
              return any(getattr(f, '__isabstractmethod__', False) for
                         f in (self._fget, self._fset, self._fdel))

  Примітка

  На відміну від абстрактних методів Java, ці абстрактні методи можуть мати реалізацію. Цю реалізацію можна викликати через механізм `super()` з класу, який її замінює. Це може бути корисним як кінцева точка для супервиклику в структурі, яка використовує кооперативне множинне успадкування.

The `abc` module also supports the following legacy decorators:

@abc.abstractclassmethod

  Нове в версії 3.2.

  Застаріло починаючи з версії 3.3: Тепер можна використовувати `classmethod` з `abstractmethod()`, що робить цей декоратор зайвим.

  Підклас вбудованого `classmethod()`, що вказує на абстрактний метод класу. В іншому він схожий на `abstractmethod()`.

  Цей спеціальний випадок застарів, оскільки декоратор `classmethod()` тепер правильно ідентифікується як абстрактний, коли застосовується до абстрактного методу:

      class C(ABC):
          @classmethod
          @abstractmethod
          def my_abstract_classmethod(cls, arg):
              ...

@abc.abstractstaticmethod

  Нове в версії 3.2.

  Застаріло починаючи з версії 3.3: Тепер можна використовувати `staticmethod` з `abstractmethod()`, що робить цей декоратор зайвим.

  Підклас вбудованого `staticmethod()`, що вказує на абстрактний статичний метод. В іншому він схожий на `abstractmethod()`.

  Цей окремий випадок застарів, оскільки декоратор `staticmethod()` тепер правильно ідентифікується як абстрактний, коли застосовується до абстрактного методу:

      class C(ABC):
          @staticmethod
          @abstractmethod
          def my_abstract_staticmethod(arg):
              ...

@abc.abstractproperty

  Застаріло починаючи з версії 3.3: Тепер можна використовувати `property`, `property.getter()`, `property.setter()` і `property.deleter()` з `abstractmethod()`, створюючи цей декоратор надлишковий.

  Підклас вбудованої `property()`, що вказує на абстрактну властивість.

  Цей окремий випадок застарів, оскільки декоратор `property()` тепер правильно ідентифікується як абстрактний, коли застосовується до абстрактного методу:

      class C(ABC):
          @property
          @abstractmethod
          def my_abstract_property(self):
              ...

  Наведений вище приклад визначає властивість лише для читання; ви також можете визначити абстрактну властивість читання-запису, відповідним чином позначивши один або більше основних методів як абстрактні:

      class C(ABC):
          @property
          def x(self):
              ...

          @x.setter
          @abstractmethod
          def x(self, val):
              ...

  Якщо лише деякі компоненти є абстрактними, лише ці компоненти потрібно оновити, щоб створити конкретну властивість у підкласі:

      class D(C):
          @C.x.setter
          def x(self, val):
              ...

The `abc` module also provides the following functions:

abc.get_cache_token()

  Повертає поточний маркер кешу абстрактного базового класу.

  Маркер — це непрозорий об’єкт (який підтримує перевірку рівності), що ідентифікує поточну версію кешу абстрактного базового класу для віртуальних підкласів. Маркер змінюється з кожним викликом `ABCMeta.register()` на будь-якому ABC.

  Нове в версії 3.4.

abc.update_abstractmethods(cls)

  Функція для повторного обчислення статусу абстракції абстрактного класу. Цю функцію слід викликати, якщо абстрактні методи класу були реалізовані або змінені після його створення. Зазвичай цю функцію слід викликати з декоратора класу.

  Повертає cls, щоб дозволити використання як декоратора класу.

  Якщо cls не є екземпляром `ABCMeta`, нічого не робить.

  Примітка

  Ця функція передбачає, що суперкласи cls вже оновлені. Він не оновлює жодних підкласів.

  Нове в версії 3.10.

Виноски

[1]

Програмісти на C++ повинні мати на увазі, що концепція віртуального базового класу Python не збігається з концепцією C++.