diff options
| author | Craig Jennings <c@cjennings.net> | 2024-04-07 13:41:34 -0500 |
|---|---|---|
| committer | Craig Jennings <c@cjennings.net> | 2024-04-07 13:41:34 -0500 |
| commit | 754bbf7a25a8dda49b5d08ef0d0443bbf5af0e36 (patch) | |
| tree | f1190704f78f04a2b0b4c977d20fe96a828377f1 /devdocs/python~3.12/library%2Fabc.html | |
new repository
Diffstat (limited to 'devdocs/python~3.12/library%2Fabc.html')
| -rw-r--r-- | devdocs/python~3.12/library%2Fabc.html | 144 |
1 files changed, 144 insertions, 0 deletions
diff --git a/devdocs/python~3.12/library%2Fabc.html b/devdocs/python~3.12/library%2Fabc.html new file mode 100644 index 00000000..a8ddfaf6 --- /dev/null +++ b/devdocs/python~3.12/library%2Fabc.html @@ -0,0 +1,144 @@ + <span id="abc-abstract-base-classes"></span><h1>abc — Abstract Base Classes</h1> <p><strong>Source code:</strong> <a class="reference external" href="https://github.com/python/cpython/tree/3.12/Lib/abc.py">Lib/abc.py</a></p> <p>This module provides the infrastructure for defining <a class="reference internal" href="../glossary#term-abstract-base-class"><span class="xref std std-term">abstract base classes</span></a> (ABCs) in Python, as outlined in <span class="target" id="index-0"></span><a class="pep reference external" href="https://peps.python.org/pep-3119/"><strong>PEP 3119</strong></a>; see the PEP for why this was added to Python. (See also <span class="target" id="index-1"></span><a class="pep reference external" href="https://peps.python.org/pep-3141/"><strong>PEP 3141</strong></a> and the <a class="reference internal" href="numbers#module-numbers" title="numbers: Numeric abstract base classes (Complex, Real, Integral, etc.)."><code>numbers</code></a> module regarding a type hierarchy for numbers based on ABCs.)</p> <p>The <a class="reference internal" href="collections#module-collections" title="collections: Container datatypes"><code>collections</code></a> module has some concrete classes that derive from ABCs; these can, of course, be further derived. In addition, the <a class="reference internal" href="collections.abc#module-collections.abc" title="collections.abc: Abstract base classes for containers"><code>collections.abc</code></a> submodule has some ABCs that can be used to test whether a class or instance provides a particular interface, for example, if it is <a class="reference internal" href="../glossary#term-hashable"><span class="xref std std-term">hashable</span></a> or if it is a <a class="reference internal" href="../glossary#term-mapping"><span class="xref std std-term">mapping</span></a>.</p> <p>This module provides the metaclass <a class="reference internal" href="#abc.ABCMeta" title="abc.ABCMeta"><code>ABCMeta</code></a> for defining ABCs and a helper class <a class="reference internal" href="#abc.ABC" title="abc.ABC"><code>ABC</code></a> to alternatively define ABCs through inheritance:</p> <dl class="py class"> <dt class="sig sig-object py" id="abc.ABC"> +<code>class abc.ABC</code> </dt> <dd> +<p>A helper class that has <a class="reference internal" href="#abc.ABCMeta" title="abc.ABCMeta"><code>ABCMeta</code></a> as its metaclass. With this class, an abstract base class can be created by simply deriving from <code>ABC</code> avoiding sometimes confusing metaclass usage, for example:</p> <pre data-language="python">from abc import ABC + +class MyABC(ABC): + pass +</pre> <p>Note that the type of <code>ABC</code> is still <a class="reference internal" href="#abc.ABCMeta" title="abc.ABCMeta"><code>ABCMeta</code></a>, therefore inheriting from <code>ABC</code> 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 <code>ABCMeta</code> directly, for example:</p> <pre data-language="python">from abc import ABCMeta + +class MyABC(metaclass=ABCMeta): + pass +</pre> <div class="versionadded"> <p><span class="versionmodified added">New in version 3.4.</span></p> </div> </dd> +</dl> <dl class="py class"> <dt class="sig sig-object py" id="abc.ABCMeta"> +<code>class abc.ABCMeta</code> </dt> <dd> +<p>Metaclass for defining Abstract Base Classes (ABCs).</p> <p>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 <a class="reference internal" href="functions#issubclass" title="issubclass"><code>issubclass()</code></a> 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 <a class="reference internal" href="functions#super" title="super"><code>super()</code></a>). <a class="footnote-reference brackets" href="#id2" id="id1">1</a></p> <p>Classes created with a metaclass of <code>ABCMeta</code> have the following method:</p> <dl class="py method"> <dt class="sig sig-object py" id="abc.ABCMeta.register"> +<code>register(subclass)</code> </dt> <dd> +<p>Register <em>subclass</em> as a “virtual subclass” of this ABC. For example:</p> <pre data-language="python">from abc import ABC + +class MyABC(ABC): + pass + +MyABC.register(tuple) + +assert issubclass(tuple, MyABC) +assert isinstance((), MyABC) +</pre> <div class="versionchanged"> <p><span class="versionmodified changed">Changed in version 3.3: </span>Returns the registered subclass, to allow usage as a class decorator.</p> </div> <div class="versionchanged"> <p><span class="versionmodified changed">Changed in version 3.4: </span>To detect calls to <code>register()</code>, you can use the <a class="reference internal" href="#abc.get_cache_token" title="abc.get_cache_token"><code>get_cache_token()</code></a> function.</p> </div> </dd> +</dl> <p>You can also override this method in an abstract base class:</p> <dl class="py method"> <dt class="sig sig-object py" id="abc.ABCMeta.__subclasshook__"> +<code>__subclasshook__(subclass)</code> </dt> <dd> +<p>(Must be defined as a class method.)</p> <p>Check whether <em>subclass</em> is considered a subclass of this ABC. This means that you can customize the behavior of <a class="reference internal" href="functions#issubclass" title="issubclass"><code>issubclass()</code></a> further without the need to call <a class="reference internal" href="#abc.ABCMeta.register" title="abc.ABCMeta.register"><code>register()</code></a> on every class you want to consider a subclass of the ABC. (This class method is called from the <a class="reference internal" href="../reference/datamodel#class.__subclasscheck__" title="class.__subclasscheck__"><code>__subclasscheck__()</code></a> method of the ABC.)</p> <p>This method should return <code>True</code>, <code>False</code> or <code>NotImplemented</code>. If it returns <code>True</code>, the <em>subclass</em> is considered a subclass of this ABC. If it returns <code>False</code>, the <em>subclass</em> is not considered a subclass of this ABC, even if it would normally be one. If it returns <code>NotImplemented</code>, the subclass check is continued with the usual mechanism.</p> </dd> +</dl> <p>For a demonstration of these concepts, look at this example ABC definition:</p> <pre data-language="python">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) +</pre> <p>The ABC <code>MyIterable</code> defines the standard iterable method, <a class="reference internal" href="stdtypes#iterator.__iter__" title="iterator.__iter__"><code>__iter__()</code></a>, as an abstract method. The implementation given here can still be called from subclasses. The <code>get_iterator()</code> method is also part of the <code>MyIterable</code> abstract base class, but it does not have to be overridden in non-abstract derived classes.</p> <p>The <a class="reference internal" href="#abc.ABCMeta.__subclasshook__" title="abc.ABCMeta.__subclasshook__"><code>__subclasshook__()</code></a> class method defined here says that any class that has an <a class="reference internal" href="stdtypes#iterator.__iter__" title="iterator.__iter__"><code>__iter__()</code></a> method in its <a class="reference internal" href="stdtypes#object.__dict__" title="object.__dict__"><code>__dict__</code></a> (or in that of one of its base classes, accessed via the <a class="reference internal" href="stdtypes#class.__mro__" title="class.__mro__"><code>__mro__</code></a> list) is considered a <code>MyIterable</code> too.</p> <p>Finally, the last line makes <code>Foo</code> a virtual subclass of <code>MyIterable</code>, even though it does not define an <a class="reference internal" href="stdtypes#iterator.__iter__" title="iterator.__iter__"><code>__iter__()</code></a> method (it uses the old-style iterable protocol, defined in terms of <a class="reference internal" href="../reference/datamodel#object.__len__" title="object.__len__"><code>__len__()</code></a> and <a class="reference internal" href="../reference/datamodel#object.__getitem__" title="object.__getitem__"><code>__getitem__()</code></a>). Note that this will not make <code>get_iterator</code> available as a method of <code>Foo</code>, so it is provided separately.</p> </dd> +</dl> <p>The <code>abc</code> module also provides the following decorator:</p> <dl class="py function"> <dt class="sig sig-object py" id="abc.abstractmethod"> +<code>@abc.abstractmethod</code> </dt> <dd> +<p>A decorator indicating abstract methods.</p> <p>Using this decorator requires that the class’s metaclass is <a class="reference internal" href="#abc.ABCMeta" title="abc.ABCMeta"><code>ABCMeta</code></a> or is derived from it. A class that has a metaclass derived from <code>ABCMeta</code> 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. <code>abstractmethod()</code> may be used to declare abstract methods for properties and descriptors.</p> <p>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 <a class="reference internal" href="#abc.update_abstractmethods" title="abc.update_abstractmethods"><code>update_abstractmethods()</code></a> function. The <code>abstractmethod()</code> only affects subclasses derived using regular inheritance; “virtual subclasses” registered with the ABC’s <a class="reference internal" href="#abc.ABCMeta.register" title="abc.ABCMeta.register"><code>register()</code></a> method are not affected.</p> <p>When <code>abstractmethod()</code> is applied in combination with other method descriptors, it should be applied as the innermost decorator, as shown in the following usage examples:</p> <pre data-language="python">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) +</pre> <p>In order to correctly interoperate with the abstract base class machinery, the descriptor must identify itself as abstract using <code>__isabstractmethod__</code>. In general, this attribute should be <code>True</code> if any of the methods used to compose the descriptor are abstract. For example, Python’s built-in <a class="reference internal" href="functions#property" title="property"><code>property</code></a> does the equivalent of:</p> <pre data-language="python">class Descriptor: + ... + @property + def __isabstractmethod__(self): + return any(getattr(f, '__isabstractmethod__', False) for + f in (self._fget, self._fset, self._fdel)) +</pre> <div class="admonition note"> <p class="admonition-title">Note</p> <p>Unlike Java abstract methods, these abstract methods may have an implementation. This implementation can be called via the <a class="reference internal" href="functions#super" title="super"><code>super()</code></a> 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.</p> </div> </dd> +</dl> <p>The <code>abc</code> module also supports the following legacy decorators:</p> <dl class="py function"> <dt class="sig sig-object py" id="abc.abstractclassmethod"> +<code>@abc.abstractclassmethod</code> </dt> <dd> +<div class="versionadded"> <p><span class="versionmodified added">New in version 3.2.</span></p> </div> <div class="deprecated"> <p><span class="versionmodified deprecated">Deprecated since version 3.3: </span>It is now possible to use <a class="reference internal" href="functions#classmethod" title="classmethod"><code>classmethod</code></a> with <a class="reference internal" href="#abc.abstractmethod" title="abc.abstractmethod"><code>abstractmethod()</code></a>, making this decorator redundant.</p> </div> <p>A subclass of the built-in <a class="reference internal" href="functions#classmethod" title="classmethod"><code>classmethod()</code></a>, indicating an abstract classmethod. Otherwise it is similar to <a class="reference internal" href="#abc.abstractmethod" title="abc.abstractmethod"><code>abstractmethod()</code></a>.</p> <p>This special case is deprecated, as the <a class="reference internal" href="functions#classmethod" title="classmethod"><code>classmethod()</code></a> decorator is now correctly identified as abstract when applied to an abstract method:</p> <pre data-language="python">class C(ABC): + @classmethod + @abstractmethod + def my_abstract_classmethod(cls, arg): + ... +</pre> </dd> +</dl> <dl class="py function"> <dt class="sig sig-object py" id="abc.abstractstaticmethod"> +<code>@abc.abstractstaticmethod</code> </dt> <dd> +<div class="versionadded"> <p><span class="versionmodified added">New in version 3.2.</span></p> </div> <div class="deprecated"> <p><span class="versionmodified deprecated">Deprecated since version 3.3: </span>It is now possible to use <a class="reference internal" href="functions#staticmethod" title="staticmethod"><code>staticmethod</code></a> with <a class="reference internal" href="#abc.abstractmethod" title="abc.abstractmethod"><code>abstractmethod()</code></a>, making this decorator redundant.</p> </div> <p>A subclass of the built-in <a class="reference internal" href="functions#staticmethod" title="staticmethod"><code>staticmethod()</code></a>, indicating an abstract staticmethod. Otherwise it is similar to <a class="reference internal" href="#abc.abstractmethod" title="abc.abstractmethod"><code>abstractmethod()</code></a>.</p> <p>This special case is deprecated, as the <a class="reference internal" href="functions#staticmethod" title="staticmethod"><code>staticmethod()</code></a> decorator is now correctly identified as abstract when applied to an abstract method:</p> <pre data-language="python">class C(ABC): + @staticmethod + @abstractmethod + def my_abstract_staticmethod(arg): + ... +</pre> </dd> +</dl> <dl class="py function"> <dt class="sig sig-object py" id="abc.abstractproperty"> +<code>@abc.abstractproperty</code> </dt> <dd> +<div class="deprecated"> <p><span class="versionmodified deprecated">Deprecated since version 3.3: </span>It is now possible to use <a class="reference internal" href="functions#property" title="property"><code>property</code></a>, <a class="reference internal" href="functions#property.getter" title="property.getter"><code>property.getter()</code></a>, <a class="reference internal" href="functions#property.setter" title="property.setter"><code>property.setter()</code></a> and <a class="reference internal" href="functions#property.deleter" title="property.deleter"><code>property.deleter()</code></a> with <a class="reference internal" href="#abc.abstractmethod" title="abc.abstractmethod"><code>abstractmethod()</code></a>, making this decorator redundant.</p> </div> <p>A subclass of the built-in <a class="reference internal" href="functions#property" title="property"><code>property()</code></a>, indicating an abstract property.</p> <p>This special case is deprecated, as the <a class="reference internal" href="functions#property" title="property"><code>property()</code></a> decorator is now correctly identified as abstract when applied to an abstract method:</p> <pre data-language="python">class C(ABC): + @property + @abstractmethod + def my_abstract_property(self): + ... +</pre> <p>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:</p> <pre data-language="python">class C(ABC): + @property + def x(self): + ... + + @x.setter + @abstractmethod + def x(self, val): + ... +</pre> <p>If only some components are abstract, only those components need to be updated to create a concrete property in a subclass:</p> <pre data-language="python">class D(C): + @C.x.setter + def x(self, val): + ... +</pre> </dd> +</dl> <p>The <code>abc</code> module also provides the following functions:</p> <dl class="py function"> <dt class="sig sig-object py" id="abc.get_cache_token"> +<code>abc.get_cache_token()</code> </dt> <dd> +<p>Returns the current abstract base class cache token.</p> <p>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 <a class="reference internal" href="#abc.ABCMeta.register" title="abc.ABCMeta.register"><code>ABCMeta.register()</code></a> on any ABC.</p> <div class="versionadded"> <p><span class="versionmodified added">New in version 3.4.</span></p> </div> </dd> +</dl> <dl class="py function"> <dt class="sig sig-object py" id="abc.update_abstractmethods"> +<code>abc.update_abstractmethods(cls)</code> </dt> <dd> +<p>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.</p> <p>Returns <em>cls</em>, to allow usage as a class decorator.</p> <p>If <em>cls</em> is not an instance of <a class="reference internal" href="#abc.ABCMeta" title="abc.ABCMeta"><code>ABCMeta</code></a>, does nothing.</p> <div class="admonition note"> <p class="admonition-title">Note</p> <p>This function assumes that <em>cls</em>’s superclasses are already updated. It does not update any subclasses.</p> </div> <div class="versionadded"> <p><span class="versionmodified added">New in version 3.10.</span></p> </div> </dd> +</dl> <h4 class="rubric">Footnotes</h4> <dl class="footnote brackets"> <dt class="label" id="id2"> +<code>1</code> </dt> <dd> +<p>C++ programmers should note that Python’s virtual base class concept is not the same as C++’s.</p> </dd> </dl> <div class="_attribution"> + <p class="_attribution-p"> + © 2001–2023 Python Software Foundation<br>Licensed under the PSF License.<br> + <a href="https://docs.python.org/3.12/library/abc.html" class="_attribution-link">https://docs.python.org/3.12/library/abc.html</a> + </p> +</div> |
