Spaces:
Running on Zero
Running on Zero
| # `!abc`{.interpreted-text role="mod"} \-\-- Abstract Base Classes | |
| ::: {.module synopsis="Abstract base classes according to :pep:`3119`."} | |
| abc | |
| ::: | |
| **Source code:** `Lib/abc.py`{.interpreted-text role="source"} | |
| ------------------------------------------------------------------------ | |
| This module provides the infrastructure for defining `abstract base | |
| classes <abstract base class>`{.interpreted-text role="term"} (ABCs) in Python, as outlined in `3119`{.interpreted-text role="pep"}; see the PEP for why this was added to Python. (See also `3141`{.interpreted-text role="pep"} and the `numbers`{.interpreted-text role="mod"} module regarding a type hierarchy for numbers based on ABCs.) | |
| The `collections`{.interpreted-text role="mod"} module has some concrete classes that derive from ABCs; these can, of course, be further derived. In addition, the `collections.abc`{.interpreted-text role="mod"} 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`{.interpreted-text role="term"} or if it is a `mapping`{.interpreted-text role="term"}. | |
| This module provides the metaclass `ABCMeta`{.interpreted-text role="class"} for defining ABCs and a helper class `ABC`{.interpreted-text role="class"} to alternatively define ABCs through inheritance: | |
| :::: ABC | |
| A helper class that has `ABCMeta`{.interpreted-text role="class"} as its metaclass. With this class, an abstract base class can be created by simply deriving from `!ABC`{.interpreted-text role="class"} avoiding sometimes confusing metaclass usage, for example: | |
| from abc import ABC | |
| class MyABC(ABC): | |
| pass | |
| Note that the type of `!ABC`{.interpreted-text role="class"} is still `ABCMeta`{.interpreted-text role="class"}, therefore inheriting from `!ABC`{.interpreted-text role="class"} 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`{.interpreted-text role="class"} directly, for example: | |
| from abc import ABCMeta | |
| class MyABC(metaclass=ABCMeta): | |
| pass | |
| ::: versionadded | |
| 3.4 | |
| ::: | |
| :::: | |
| ::::::: ABCMeta | |
| Metaclass for defining Abstract Base Classes (ABCs). | |
| Use 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`{.interpreted-text role="func"} 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`{.interpreted-text role="func"}).[^1] | |
| Classes created with a metaclass of `!ABCMeta`{.interpreted-text role="class"} have the following method: | |
| ::::: method | |
| register(subclass) | |
| Register *subclass* as a \"virtual subclass\" of this ABC. For example: | |
| from abc import ABC | |
| class MyABC(ABC): | |
| pass | |
| MyABC.register(tuple) | |
| assert issubclass(tuple, MyABC) | |
| assert isinstance((), MyABC) | |
| ::: versionchanged | |
| 3.3 Returns the registered subclass, to allow usage as a class decorator. | |
| ::: | |
| ::: versionchanged | |
| 3.4 To detect calls to `!register`{.interpreted-text role="meth"}, you can use the `get_cache_token`{.interpreted-text role="func"} function. | |
| ::: | |
| ::::: | |
| You can also override this method in an abstract base class: | |
| ::: method | |
| \_\_subclasshook\_\_(subclass) | |
| (Must be defined as a class method.) | |
| Check whether *subclass* is considered a subclass of this ABC. This means that you can customize the behavior of `issubclass`{.interpreted-text role="func"} further without the need to call `register`{.interpreted-text role="meth"} on every class you want to consider a subclass of the ABC. (This class method is called from the `~type.__subclasscheck__`{.interpreted-text role="meth"} method of the ABC.) | |
| This method should return `True`, `False` or `NotImplemented`{.interpreted-text role="data"}. 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`{.interpreted-text role="data"}, the subclass check is continued with the usual mechanism. | |
| ::: | |
| For a demonstration of these concepts, look at this example ABC definition: | |
| 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, `~object.__iter__`{.interpreted-text role="meth"}, as an abstract method. The implementation given here can still be called from subclasses. The `!get_iterator`{.interpreted-text role="meth"} 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__`{.interpreted-text role="meth"} class method defined here says that any class that has an `~object.__iter__`{.interpreted-text role="meth"} method in its `~object.__dict__`{.interpreted-text role="attr"} (or in that of one of its base classes, accessed via the `~type.__mro__`{.interpreted-text role="attr"} list) is considered a `MyIterable` too. | |
| Finally, the last line makes `Foo` a virtual subclass of `MyIterable`, even though it does not define an `~object.__iter__`{.interpreted-text role="meth"} method (it uses the old-style iterable protocol, defined in terms of `~object.__len__`{.interpreted-text role="meth"} and `~object.__getitem__`{.interpreted-text role="meth"}). Note that this will not make `get_iterator` available as a method of `Foo`, so it is provided separately. | |
| ::::::: | |
| The `!abc`{.interpreted-text role="mod"} module also provides the following decorator: | |
| ::::: decorator | |
| abstractmethod | |
| A decorator indicating abstract methods. | |
| Using this decorator requires that the class\'s metaclass is `ABCMeta`{.interpreted-text role="class"} or is derived from it. A class that has a metaclass derived from `!ABCMeta`{.interpreted-text role="class"} 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`{.interpreted-text role="func"} 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`{.interpreted-text role="func"} function. The `!abstractmethod`{.interpreted-text role="func"} only affects subclasses derived using regular inheritance; \"virtual subclasses\" registered with the ABC\'s `~ABCMeta.register`{.interpreted-text role="meth"} method are not affected. | |
| When `!abstractmethod`{.interpreted-text role="func"} 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__`{.interpreted-text role="attr"}. 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`{.interpreted-text role="class"} 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)) | |
| :::: note | |
| ::: title | |
| Note | |
| ::: | |
| Unlike Java abstract methods, these abstract methods may have an implementation. This implementation can be called via the `super`{.interpreted-text role="func"} mechanism from the class that overrides it. This could be useful as an end-point for a super-call in a framework that uses cooperative multiple-inheritance. | |
| :::: | |
| ::::: | |
| The `!abc`{.interpreted-text role="mod"} module also supports the following legacy decorators: | |
| ::::: decorator | |
| abstractclassmethod | |
| ::: versionadded | |
| 3.2 | |
| ::: | |
| ::: deprecated | |
| 3.3 It is now possible to use `classmethod`{.interpreted-text role="class"} with `abstractmethod`{.interpreted-text role="func"}, making this decorator redundant. | |
| ::: | |
| A subclass of the built-in `classmethod`{.interpreted-text role="func"}, indicating an abstract classmethod. Otherwise it is similar to `abstractmethod`{.interpreted-text role="func"}. | |
| This special case is deprecated, as the `classmethod`{.interpreted-text role="func"} decorator is now correctly identified as abstract when applied to an abstract method: | |
| class C(ABC): | |
| @classmethod | |
| @abstractmethod | |
| def my_abstract_classmethod(cls, arg): | |
| ... | |
| ::::: | |
| ::::: decorator | |
| abstractstaticmethod | |
| ::: versionadded | |
| 3.2 | |
| ::: | |
| ::: deprecated | |
| 3.3 It is now possible to use `staticmethod`{.interpreted-text role="class"} with `abstractmethod`{.interpreted-text role="func"}, making this decorator redundant. | |
| ::: | |
| A subclass of the built-in `staticmethod`{.interpreted-text role="func"}, indicating an abstract staticmethod. Otherwise it is similar to `abstractmethod`{.interpreted-text role="func"}. | |
| This special case is deprecated, as the `staticmethod`{.interpreted-text role="func"} decorator is now correctly identified as abstract when applied to an abstract method: | |
| class C(ABC): | |
| @staticmethod | |
| @abstractmethod | |
| def my_abstract_staticmethod(arg): | |
| ... | |
| ::::: | |
| :::: decorator | |
| abstractproperty | |
| ::: deprecated | |
| 3.3 It is now possible to use `property`{.interpreted-text role="class"}, `property.getter`{.interpreted-text role="meth"}, `property.setter`{.interpreted-text role="meth"} and `property.deleter`{.interpreted-text role="meth"} with `abstractmethod`{.interpreted-text role="func"}, making this decorator redundant. | |
| ::: | |
| A subclass of the built-in `property`{.interpreted-text role="func"}, indicating an abstract property. | |
| This special case is deprecated, as the `property`{.interpreted-text role="func"} decorator is now correctly identified as abstract when applied to an abstract method: | |
| class C(ABC): | |
| @property | |
| @abstractmethod | |
| def my_abstract_property(self): | |
| ... | |
| The above example defines a read-only property; you can also define a read-write abstract property by appropriately marking one or more of the underlying methods as abstract: | |
| class C(ABC): | |
| @property | |
| def x(self): | |
| ... | |
| @x.setter | |
| @abstractmethod | |
| def x(self, val): | |
| ... | |
| If only some components are abstract, only those components need to be updated to create a concrete property in a subclass: | |
| class D(C): | |
| @C.x.setter | |
| def x(self, val): | |
| ... | |
| :::: | |
| The `!abc`{.interpreted-text role="mod"} module also provides the following functions: | |
| :::: function | |
| get_cache_token() | |
| Returns the current abstract base class cache token. | |
| The token is an opaque object (that supports equality testing) identifying the current version of the abstract base class cache for virtual subclasses. The token changes with every call to `ABCMeta.register`{.interpreted-text role="meth"} on any ABC. | |
| ::: versionadded | |
| 3.4 | |
| ::: | |
| :::: | |
| :::::: function | |
| update_abstractmethods(cls) | |
| A function to recalculate an abstract class\'s abstraction status. This function should be called if a class\'s abstract methods have been implemented or changed after it was created. Usually, this function should be called from within a class decorator. | |
| Returns *cls*, to allow usage as a class decorator. | |
| If *cls* is not an instance of `ABCMeta`{.interpreted-text role="class"}, does nothing. | |
| :::: note | |
| ::: title | |
| Note | |
| ::: | |
| This function assumes that *cls*\'s superclasses are already updated. It does not update any subclasses. | |
| :::: | |
| ::: versionadded | |
| 3.10 | |
| ::: | |
| :::::: | |
| **Footnotes** | |
| [^1]: C++ programmers should note that Python\'s virtual base class concept is not the same as C++\'s. | |