“Python/docs/3.9/library/abc”的版本间差异

来自菜鸟教程
Python/docs/3.9/library/abc
跳转至:导航、​搜索
(autoload)
 
(Page commit)
 
第1行: 第1行:
 +
{{DISPLAYTITLE:abc — 抽象基类 — Python 文档}}
 
<div id="module-abc" class="section">
 
<div id="module-abc" class="section">
  
 
<span id="abc-abstract-base-classes"></span>
 
<span id="abc-abstract-base-classes"></span>
= [[#module-abc|<code>abc</code>]] --- Abstract Base Classes =
+
= abc — 抽象基类 =
  
'''Source code:''' [https://github.com/python/cpython/tree/3.9/Lib/abc.py Lib/abc.py]
+
'''源代码:''' [[#id1|<span id="id2" class="problematic">:source:`Lib/abc.py`</span>]]
  
This module provides the infrastructure for defining [[../../glossary#term-abstract-base-class|<span class="xref std std-term">abstract base
 
classes</span>]] (ABCs) in Python, as outlined in <span id="index-0" class="target"></span>[https://www.python.org/dev/peps/pep-3119 '''PEP 3119'''];
 
see the PEP for why this was added to Python. (See also <span id="index-1" class="target"></span>[https://www.python.org/dev/peps/pep-3141 '''PEP 3141'''] and the
 
[[../numbers#module-numbers|<code>numbers</code>]] module regarding a type hierarchy for numbers based on ABCs.)
 
  
The [[../collections#module-collections|<code>collections</code>]] module has some concrete classes that derive from
+
-----
ABCs; these can, of course, be further derived. In addition, the
 
[[../collections.abc#module-collections|<code>collections.abc</code>]] 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.
 
  
This module provides the metaclass [[#abc.ABCMeta|<code>ABCMeta</code>]] for defining ABCs and
+
该模块提供了在 Python 中定义 [[../../glossary#term-abstract-base-class|抽象基类]] (ABC) 的基础结构,如 <span id="index-0" class="target"></span>[https://www.python.org/dev/peps/pep-3119 PEP 3119] 中所述; 请参阅 PEP 了解为什么将其添加到 Python 中。 (另请参阅 <span id="index-1" class="target"></span>[https://www.python.org/dev/peps/pep-3141 PEP 3141] 和 [[../numbers#module-numbers|numbers]] 模块,了解基于 ABC 的数字的类型层次结构。)
a helper class [[#abc.ABC|<code>ABC</code>]] to alternatively define ABCs through inheritance:
+
 
 +
[[../collections#module-collections|collections]] 模块有一些从 ABC 派生的具体类; 当然,这些还可以进一步推导出来。 此外,[[../collections.abc#module-collections|collections.abc]] 子模块有一些 ABC,可用于测试类或实例是否提供特定接口,例如,是否可散列或是否是映射。
 +
 
 +
该模块提供了用于定义 ABC 的元类 [[#abc.ABCMeta|ABCMeta]] 和用于通过继承交替定义 ABC 的辅助类 [[#abc.ABC|ABC]]
  
 
<dl>
 
<dl>
<dt>''class'' <code>abc.</code><code>ABC</code></dt>
+
<dt>''<span class="pre">class</span>'' <span class="sig-prename descclassname"><span class="pre">abc.</span></span><span class="sig-name descname"><span class="pre">ABC</span></span></dt>
<dd><p>A helper class that has [[#abc.ABCMeta|<code>ABCMeta</code>]] as its metaclass. With this class,
+
<dd><p>具有 [[#abc.ABCMeta|ABCMeta]] 作为其元类的辅助类。 使用这个类,可以通过简单地从 [[#abc.ABC|ABC]] 派生来创建抽象基类,避免有时混淆元类的用法,例如:</p>
an abstract base class can be created by simply deriving from [[#abc.ABC|<code>ABC</code>]]
 
avoiding sometimes confusing metaclass usage, for example:</p>
 
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
  
 
<div class="highlight">
 
<div class="highlight">
  
<pre>from abc import ABC
+
<syntaxhighlight lang="python3">from abc import ABC
  
 
class MyABC(ABC):
 
class MyABC(ABC):
     pass</pre>
+
     pass</syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
<p>Note that the type of [[#abc.ABC|<code>ABC</code>]] is still [[#abc.ABCMeta|<code>ABCMeta</code>]], therefore
+
<p>请注意,[[#abc.ABC|ABC]] 的类型仍然是 [[#abc.ABCMeta|ABCMeta]],因此从 [[#abc.ABC|ABC]] 继承需要有关元类使用的常规预防措施,因为多重继承可能会导致元类冲突。 也可以通过传递 metaclass 关键字并直接使用 [[#abc.ABCMeta|ABCMeta]] 来定义抽象基类,例如:</p>
inheriting from [[#abc.ABC|<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 [[#abc.ABCMeta|<code>ABCMeta</code>]] directly, for example:</p>
 
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
  
 
<div class="highlight">
 
<div class="highlight">
  
<pre>from abc import ABCMeta
+
<syntaxhighlight lang="python3">from abc import ABCMeta
  
 
class MyABC(metaclass=ABCMeta):
 
class MyABC(metaclass=ABCMeta):
     pass</pre>
+
     pass</syntaxhighlight>
  
 
</div>
 
</div>
第56行: 第46行:
 
<div class="versionadded">
 
<div class="versionadded">
  
<p><span class="versionmodified added">3.4 新版功能.</span></p>
+
<p><span class="versionmodified added">3.4 版中的新功能。</span></p>
  
 
</div></dd></dl>
 
</div></dd></dl>
  
 
<dl>
 
<dl>
<dt>''class'' <code>abc.</code><code>ABCMeta</code></dt>
+
<dt>''<span class="pre">class</span>'' <span class="sig-prename descclassname"><span class="pre">abc.</span></span><span class="sig-name descname"><span class="pre">ABCMeta</span></span></dt>
<dd><p>Metaclass for defining Abstract Base Classes (ABCs).</p>
+
<dd><p>用于定义抽象基类 (ABC) 的元类。</p>
<p>Use this metaclass to create an ABC. An ABC can be subclassed directly, and
+
<p>使用这个元类来创建一个 ABC。 ABC 可以直接子类化,然后充当混合类。 您还可以将不相关的具体类(甚至内置类)和不相关的 ABC 注册为“虚拟子类”——这些及其后代将被内置 [[../functions#issubclass|issubclass()]] 函数视为注册 ABC 的子类,但注册 ABC 不会出现在他们的 MRO(方法解析顺序)中,注册 ABC 定义的方法实现也不会被调用(甚至不能通过 [[../functions#super|super()]])。 [[#id4|1]]</p>
then acts as a mix-in class. You can also register unrelated concrete
+
<p>使用 [[#abc.ABCMeta|ABCMeta]] 元类创建的类具有以下方法:</p>
classes (even built-in classes) and unrelated ABCs as &quot;virtual subclasses&quot; --
 
these and their descendants will be considered subclasses of the registering
 
ABC by the built-in [[../functions#issubclass|<code>issubclass()</code>]] 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
 
[[../functions#super|<code>super()</code>]]). [[#id2|1]]</p>
 
<p>Classes created with a metaclass of [[#abc.ABCMeta|<code>ABCMeta</code>]] have the following method:</p>
 
 
<dl>
 
<dl>
<dt><code>register</code><span class="sig-paren">(</span>''<span class="n">subclass</span>''<span class="sig-paren">)</span></dt>
+
<dt><span class="sig-name descname"><span class="pre">register</span></span><span class="sig-paren">(</span>''<span class="n"><span class="pre">subclass</span></span>''<span class="sig-paren">)</span></dt>
<dd><p>Register ''subclass'' as a &quot;virtual subclass&quot; of this ABC. For
+
<dd><p>注册 ''subclass'' 作为这个 ABC 的“虚拟子类”。 例如:</p>
example:</p>
 
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
  
 
<div class="highlight">
 
<div class="highlight">
  
<pre>from abc import ABC
+
<syntaxhighlight lang="python3">from abc import ABC
  
 
class MyABC(ABC):
 
class MyABC(ABC):
第88行: 第70行:
  
 
assert issubclass(tuple, MyABC)
 
assert issubclass(tuple, MyABC)
assert isinstance((), MyABC)</pre>
+
assert isinstance((), MyABC)</syntaxhighlight>
  
 
</div>
 
</div>
第95行: 第77行:
 
<div class="versionchanged">
 
<div class="versionchanged">
  
<p><span class="versionmodified changed">在 3.3 版更改: </span>Returns the registered subclass, to allow usage as a class decorator.</p>
+
<p><span class="versionmodified changed"> 在 3.3 版更改: </span> 返回注册的子类,以允许用作类装饰器。</p>
  
 
</div>
 
</div>
 
<div class="versionchanged">
 
<div class="versionchanged">
  
<p><span class="versionmodified changed">3.4 版更改: </span>To detect calls to [[#abc.ABCMeta.register|<code>register()</code>]], you can use the
+
<p><span class="versionmodified changed"> 3.4 版更改: </span> 要检测对 [[#abc.ABCMeta.register|register()]] 的调用,可以使用 [[#abc.get_cache_token|get_cache_token()]] 函数。</p>
[[#abc.get_cache_token|<code>get_cache_token()</code>]] function.</p>
 
  
 
</div></dd></dl>
 
</div></dd></dl>
  
<p>You can also override this method in an abstract base class:</p>
+
<p>您还可以在抽象基类中覆盖此方法:</p>
 
<dl>
 
<dl>
<dt><code>__subclasshook__</code><span class="sig-paren">(</span>''<span class="n">subclass</span>''<span class="sig-paren">)</span></dt>
+
<dt><span class="sig-name descname"><span class="pre">__subclasshook__</span></span><span class="sig-paren">(</span>''<span class="n"><span class="pre">subclass</span></span>''<span class="sig-paren">)</span></dt>
<dd><p>(Must be defined as a class method.)</p>
+
<dd><p>(必须定义为类方法。)</p>
<p>Check whether ''subclass'' is considered a subclass of this ABC. This means
+
<p>检查 ''subclass'' 是否被认为是这个 ABC 的子类。 这意味着您可以进一步自定义 <code>issubclass</code> 的行为,而无需在要考虑 ABC 子类的每个类上调用 [[#abc.ABCMeta.register|register()]]。 (此类方法是从 ABC <code>__subclasscheck__()</code> 方法调用的。)</p>
that you can customize the behavior of <code>issubclass</code> further without the
+
<p>此方法应返回 <code>True</code><code>False</code> <code>NotImplemented</code>。 如果它返回 <code>True</code>,则 ''子类'' 被视为此 ABC 的子类。 如果它返回 <code>False</code>,则 ''子类'' 不被视为此 ABC 的子类,即使它通常是一个子类。 如果它返回 <code>NotImplemented</code>,子类检查将继续使用通常的机制。</p></dd></dl>
need to call [[#abc.ABCMeta.register|<code>register()</code>]] on every class you want to consider a
 
subclass of the ABC. (This class method is called from the
 
<code>__subclasscheck__()</code> 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 ''subclass'' is considered a subclass of this ABC.
 
If it returns <code>False</code>, the ''subclass'' 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>
+
<p>要演示这些概念,请查看以下示例 ABC 定义:</p>
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
  
 
<div class="highlight">
 
<div class="highlight">
  
<pre>class Foo:
+
<syntaxhighlight lang="python3">class Foo:
 
     def __getitem__(self, index):
 
     def __getitem__(self, index):
 
         ...
 
         ...
第147行: 第119行:
 
     def __subclasshook__(cls, C):
 
     def __subclasshook__(cls, C):
 
         if cls is MyIterable:
 
         if cls is MyIterable:
             if any(&quot;__iter__&quot; in B.__dict__ for B in C.__mro__):
+
             if any("__iter__" in B.__dict__ for B in C.__mro__):
 
                 return True
 
                 return True
 
         return NotImplemented
 
         return NotImplemented
  
MyIterable.register(Foo)</pre>
+
MyIterable.register(Foo)</syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
<p>The ABC <code>MyIterable</code> defines the standard iterable method,
+
<p>ABC <code>MyIterable</code> 将标准可迭代方法 [[../stdtypes#iterator|__iter__()]] 定义为抽象方法。 这里给出的实现仍然可以从子类中调用。 <code>get_iterator()</code> 方法也是 <code>MyIterable</code> 抽象基类的一部分,但它不必在非抽象派生类中被覆盖。</p>
[[../stdtypes#iterator|<code>__iter__()</code>]], as an abstract method. The implementation given
+
<p>此处定义的 [[#abc.ABCMeta.__subclasshook__|__subclasshook__()]] 类方法表示,任何在其 [[../stdtypes#object|__dict__]](或其基类之一的方法中)具有 [[../stdtypes#iterator|__iter__()]] 方法的类,通过 [[../stdtypes#class|__mro__]] 列表访问)也被认为是 <code>MyIterable</code></p>
here can still be called from subclasses. The <code>get_iterator()</code> method
+
<p>最后,最后一行使 <code>Foo</code> 成为 <code>MyIterable</code> 的虚拟子类,即使它没有定义 [[../stdtypes#iterator|__iter__()]] 方法(它使用旧式可迭代协议,定义为 <code>__len__()</code> <code>__getitem__()</code>)。 请注意,这不会使 <code>get_iterator</code> 作为 <code>Foo</code> 的方法可用,因此单独提供。</p></dd></dl>
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 [[#abc.ABCMeta.__subclasshook__|<code>__subclasshook__()</code>]] class method defined here says that any class
 
that has an [[../stdtypes#iterator|<code>__iter__()</code>]] method in its
 
[[../stdtypes#object|<code>__dict__</code>]] (or in that of one of its base classes, accessed
 
via the [[../stdtypes#class|<code>__mro__</code>]] 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 [[../stdtypes#iterator|<code>__iter__()</code>]] method (it uses
 
the old-style iterable protocol, defined in terms of <code>__len__()</code> and
 
<code>__getitem__()</code>). 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>
 
  
The [[#module-abc|<code>abc</code>]] module also provides the following decorator:
+
[[#module-abc|abc]] 模块还提供了以下装饰器:
  
 
<dl>
 
<dl>
<dt><code>@</code><code>abc.</code><code>abstractmethod</code></dt>
+
<dt><span class="sig-prename descclassname"><span class="pre">@</span></span><span class="sig-prename descclassname"><span class="pre">abc.</span></span><span class="sig-name descname"><span class="pre">abstractmethod</span></span></dt>
<dd><p>A decorator indicating abstract methods.</p>
+
<dd><p>指示抽象方法的装饰器。</p>
<p>Using this decorator requires that the class's metaclass is [[#abc.ABCMeta|<code>ABCMeta</code>]]
+
<p>使用这个装饰器需要类的元类是 [[#abc.ABCMeta|ABCMeta]] 或者是从它派生的。 一个具有从 [[#abc.ABCMeta|ABCMeta]] 派生的元类的类不能被实例化,除非它的所有抽象方法和属性都被覆盖。 可以使用任何正常的“超级”调用机制来调用抽象方法。 [[#abc.abstractmethod|abstractmethod()]] 可用于声明属性和描述符的抽象方法。</p>
or is derived from it. A class that has a metaclass derived from
+
<p>不支持向类动态添加抽象方法,或在方法或类创建后尝试修改其抽象状态。 [[#abc.abstractmethod|abstractmethod()]] 只影响使用常规继承派生的子类; 使用 ABC <code>register()</code> 方法注册的“虚拟子类”不受影响。</p>
[[#abc.ABCMeta|<code>ABCMeta</code>]] cannot be instantiated unless all of its abstract methods
+
<p>[[#abc.abstractmethod|abstractmethod()]] 与其他方法描述符结合使用时,应作为最内层装饰器使用,如下面的使用示例所示:</p>
and properties are overridden. The abstract methods can be called using any
 
of the normal 'super' call mechanisms. [[#abc.abstractmethod|<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 not
 
supported. The [[#abc.abstractmethod|<code>abstractmethod()</code>]] only affects subclasses derived using
 
regular inheritance; &quot;virtual subclasses&quot; registered with the ABC's
 
<code>register()</code> method are not affected.</p>
 
<p>When [[#abc.abstractmethod|<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>
 
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
  
 
<div class="highlight">
 
<div class="highlight">
  
<pre>class C(ABC):
+
<syntaxhighlight lang="python3">class C(ABC):
 
     @abstractmethod
 
     @abstractmethod
 
     def my_abstract_method(self, ...):
 
     def my_abstract_method(self, ...):
第222行: 第172行:
 
     def _set_x(self, val):
 
     def _set_x(self, val):
 
         ...
 
         ...
     x = property(_get_x, _set_x)</pre>
+
     x = property(_get_x, _set_x)</syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
<p>In order to correctly interoperate with the abstract base class machinery,
+
<p>为了正确地与抽象基类机器互操作,描述符必须使用 <code>__isabstractmethod__</code> 将自己标识为抽象。 通常,如果用于组成描述符的任何方法是抽象的,则此属性应为 <code>True</code>。 例如,Python 的内置 [[../functions#property|属性]] 相当于:</p>
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 [[../functions#property|<code>property</code>]] does the equivalent of:</p>
 
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
  
 
<div class="highlight">
 
<div class="highlight">
  
<pre>class Descriptor:
+
<syntaxhighlight lang="python3">class Descriptor:
 
     ...
 
     ...
 
     @property
 
     @property
 
     def __isabstractmethod__(self):
 
     def __isabstractmethod__(self):
 
         return any(getattr(f, '__isabstractmethod__', False) for
 
         return any(getattr(f, '__isabstractmethod__', False) for
                   f in (self._fget, self._fset, self._fdel))</pre>
+
                   f in (self._fget, self._fset, self._fdel))</syntaxhighlight>
  
 
</div>
 
</div>
第248行: 第194行:
 
<div class="admonition note">
 
<div class="admonition note">
  
<p>注解</p>
+
<p>笔记</p>
<p>Unlike Java abstract methods, these abstract
+
<p>Java 抽象方法不同,这些抽象方法可能有一个实现。 这个实现可以通过覆盖它的类的 [[../functions#super|super()]] 机制调用。 在使用协作多重继承的框架中,这可以用作超级调用的端点。</p>
methods may have an implementation. This implementation can be
 
called via the [[../functions#super|<code>super()</code>]] 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>
 
</div></dd></dl>
  
The [[#module-abc|<code>abc</code>]] module also supports the following legacy decorators:
+
[[#module-abc|abc]] 模块还支持以下遗留装饰器:
  
 
<dl>
 
<dl>
<dt><code>@</code><code>abc.</code><code>abstractclassmethod</code></dt>
+
<dt><span class="sig-prename descclassname"><span class="pre">@</span></span><span class="sig-prename descclassname"><span class="pre">abc.</span></span><span class="sig-name descname"><span class="pre">abstractclassmethod</span></span></dt>
 
<dd><div class="versionadded">
 
<dd><div class="versionadded">
  
<p><span class="versionmodified added">3.2 新版功能.</span></p>
+
<p><span class="versionmodified added">3.2 版中的新功能。</span></p>
  
 
</div>
 
</div>
 
<div class="deprecated">
 
<div class="deprecated">
  
<p><span class="versionmodified deprecated">3.3 版后已移除: </span>It is now possible to use [[../functions#classmethod|<code>classmethod</code>]] with
+
<p><span class="versionmodified deprecated"> 3.3 版起已弃用:</span>现在可以将 [[../functions#classmethod|classmethod]] [[#abc.abstractmethod|abstractmethod()]] 一起使用,使该装饰器变得多余。</p>
[[#abc.abstractmethod|<code>abstractmethod()</code>]], making this decorator redundant.</p>
 
  
 
</div>
 
</div>
<p>A subclass of the built-in [[../functions#classmethod|<code>classmethod()</code>]], indicating an abstract
+
<p>内置 [[../functions#classmethod|classmethod()]] 的子类,表示抽象类方法。 否则它类似于 [[#abc.abstractmethod|abstractmethod()]]</p>
classmethod. Otherwise it is similar to [[#abc.abstractmethod|<code>abstractmethod()</code>]].</p>
+
<p>这种特殊情况已被弃用,因为 [[../functions#classmethod|classmethod()]] 装饰器现在在应用于抽象方法时被正确标识为抽象:</p>
<p>This special case is deprecated, as the [[../functions#classmethod|<code>classmethod()</code>]] decorator
 
is now correctly identified as abstract when applied to an abstract
 
method:</p>
 
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
  
 
<div class="highlight">
 
<div class="highlight">
  
<pre>class C(ABC):
+
<syntaxhighlight lang="python3">class C(ABC):
 
     @classmethod
 
     @classmethod
 
     @abstractmethod
 
     @abstractmethod
 
     def my_abstract_classmethod(cls, ...):
 
     def my_abstract_classmethod(cls, ...):
         ...</pre>
+
         ...</syntaxhighlight>
  
 
</div>
 
</div>
第293行: 第230行:
  
 
<dl>
 
<dl>
<dt><code>@</code><code>abc.</code><code>abstractstaticmethod</code></dt>
+
<dt><span class="sig-prename descclassname"><span class="pre">@</span></span><span class="sig-prename descclassname"><span class="pre">abc.</span></span><span class="sig-name descname"><span class="pre">abstractstaticmethod</span></span></dt>
 
<dd><div class="versionadded">
 
<dd><div class="versionadded">
  
<p><span class="versionmodified added">3.2 新版功能.</span></p>
+
<p><span class="versionmodified added">3.2 版中的新功能。</span></p>
  
 
</div>
 
</div>
 
<div class="deprecated">
 
<div class="deprecated">
  
<p><span class="versionmodified deprecated">3.3 版后已移除: </span>It is now possible to use [[../functions#staticmethod|<code>staticmethod</code>]] with
+
<p><span class="versionmodified deprecated"> 3.3 版起已弃用: </span> 现在可以将 [[../functions#staticmethod|staticmethod]] [[#abc.abstractmethod|abstractmethod()]] 一起使用,使该装饰器变得多余。</p>
[[#abc.abstractmethod|<code>abstractmethod()</code>]], making this decorator redundant.</p>
 
  
 
</div>
 
</div>
<p>A subclass of the built-in [[../functions#staticmethod|<code>staticmethod()</code>]], indicating an abstract
+
<p>内置 [[../functions#staticmethod|staticmethod()]] 的子类,表示抽象静态方法。 否则它类似于 [[#abc.abstractmethod|abstractmethod()]]</p>
staticmethod. Otherwise it is similar to [[#abc.abstractmethod|<code>abstractmethod()</code>]].</p>
+
<p>这种特殊情况已被弃用,因为 [[../functions#staticmethod|staticmethod()]] 装饰器现在在应用于抽象方法时被正确标识为抽象:</p>
<p>This special case is deprecated, as the [[../functions#staticmethod|<code>staticmethod()</code>]] decorator
 
is now correctly identified as abstract when applied to an abstract
 
method:</p>
 
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
  
 
<div class="highlight">
 
<div class="highlight">
  
<pre>class C(ABC):
+
<syntaxhighlight lang="python3">class C(ABC):
 
     @staticmethod
 
     @staticmethod
 
     @abstractmethod
 
     @abstractmethod
 
     def my_abstract_staticmethod(...):
 
     def my_abstract_staticmethod(...):
         ...</pre>
+
         ...</syntaxhighlight>
  
 
</div>
 
</div>
第325行: 第258行:
  
 
<dl>
 
<dl>
<dt><code>@</code><code>abc.</code><code>abstractproperty</code></dt>
+
<dt><span class="sig-prename descclassname"><span class="pre">@</span></span><span class="sig-prename descclassname"><span class="pre">abc.</span></span><span class="sig-name descname"><span class="pre">abstractproperty</span></span></dt>
 
<dd><div class="deprecated">
 
<dd><div class="deprecated">
  
<p><span class="versionmodified deprecated">3.3 版后已移除: </span>It is now possible to use [[../functions#property|<code>property</code>]], <code>property.getter()</code>,
+
<p><span class="versionmodified deprecated">3.3 版起已弃用:</span>现在可以将 [[../functions#property|属性]] <code>property.getter()</code><code>property.setter()</code> <code>property.deleter()</code> [[#abc.abstractmethod|抽象方法一起使用()]],使这个装饰器变得多余。</p>
<code>property.setter()</code> and <code>property.deleter()</code> with
 
[[#abc.abstractmethod|<code>abstractmethod()</code>]], making this decorator redundant.</p>
 
  
 
</div>
 
</div>
<p>A subclass of the built-in [[../functions#property|<code>property()</code>]], indicating an abstract
+
<p>内置 [[../functions#property|property()]] 的子类,表示抽象属性。</p>
property.</p>
+
<p>这种特殊情况已被弃用,因为 [[../functions#property|property()]] 装饰器现在在应用于抽象方法时被正确标识为抽象:</p>
<p>This special case is deprecated, as the [[../functions#property|<code>property()</code>]] decorator
 
is now correctly identified as abstract when applied to an abstract
 
method:</p>
 
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
  
 
<div class="highlight">
 
<div class="highlight">
  
<pre>class C(ABC):
+
<syntaxhighlight lang="python3">class C(ABC):
 
     @property
 
     @property
 
     @abstractmethod
 
     @abstractmethod
 
     def my_abstract_property(self):
 
     def my_abstract_property(self):
         ...</pre>
+
         ...</syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
<p>The above example defines a read-only property; you can also define a
+
<p>上面的例子定义了一个只读属性; 您还可以通过适当地将一个或多个底层方法标记为抽象来定义读写抽象属性:</p>
read-write abstract property by appropriately marking one or more of the
 
underlying methods as abstract:</p>
 
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
  
 
<div class="highlight">
 
<div class="highlight">
  
<pre>class C(ABC):
+
<syntaxhighlight lang="python3">class C(ABC):
 
     @property
 
     @property
 
     def x(self):
 
     def x(self):
第366行: 第292行:
 
     @abstractmethod
 
     @abstractmethod
 
     def x(self, val):
 
     def x(self, val):
         ...</pre>
+
         ...</syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
<p>If only some components are abstract, only those components need to be
+
<p>如果只有一些组件是抽象的,则只需更新这些组件以在子类中创建具体属性:</p>
updated to create a concrete property in a subclass:</p>
 
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
  
 
<div class="highlight">
 
<div class="highlight">
  
<pre>class D(C):
+
<syntaxhighlight lang="python3">class D(C):
 
     @C.x.setter
 
     @C.x.setter
 
     def x(self, val):
 
     def x(self, val):
         ...</pre>
+
         ...</syntaxhighlight>
  
 
</div>
 
</div>
第386行: 第311行:
 
</div></dd></dl>
 
</div></dd></dl>
  
The [[#module-abc|<code>abc</code>]] module also provides the following functions:
+
[[#module-abc|abc]] 模块还提供以下功能:
  
 
<dl>
 
<dl>
<dt><code>abc.</code><code>get_cache_token</code><span class="sig-paren">(</span><span class="sig-paren">)</span></dt>
+
<dt><span class="sig-prename descclassname"><span class="pre">abc.</span></span><span class="sig-name descname"><span class="pre">get_cache_token</span></span><span class="sig-paren">(</span><span class="sig-paren">)</span></dt>
<dd><p>Returns the current abstract base class cache token.</p>
+
<dd><p>返回当前抽象基类缓存令牌。</p>
<p>The token is an opaque object (that supports equality testing) identifying
+
<p>令牌是一个不透明的对象(支持相等性测试),用于标识虚拟子类的抽象基类缓存的当前版本。 在任何 ABC 上每次调用 [[#abc.ABCMeta.register|ABCMeta.register()]] 时,令牌都会发生变化。</p>
the current version of the abstract base class cache for virtual subclasses.
 
The token changes with every call to [[#abc.ABCMeta.register|<code>ABCMeta.register()</code>]] on any ABC.</p>
 
 
<div class="versionadded">
 
<div class="versionadded">
  
<p><span class="versionmodified added">3.4 新版功能.</span></p>
+
<p><span class="versionmodified added">3.4 版中的新功能。</span></p>
  
 
</div></dd></dl>
 
</div></dd></dl>
  
Footnotes
+
脚注
 +
 
 +
; <span class="brackets">[[#id3|1]]</span>
 +
: C++ 程序员应该注意 Python 的虚拟基类概念与 C++ 的不同。
 +
 
 +
 
 +
</div>
 +
<div class="clearer">
  
; <span class="brackets">[[#id1|1]]</span>
 
: C++ programmers should note that Python's virtual base class concept is not the same as C++'s.
 
  
  
 
</div>
 
</div>
  
[[Category:Python 3.9 中文文档]]
+
[[Category:Python 3.9 文档]]

2021年10月31日 (日) 04:51的最新版本

abc — 抽象基类

源代码: :source:`Lib/abc.py`



该模块提供了在 Python 中定义 抽象基类 (ABC) 的基础结构,如 PEP 3119 中所述; 请参阅 PEP 了解为什么将其添加到 Python 中。 (另请参阅 PEP 3141numbers 模块,了解基于 ABC 的数字的类型层次结构。)

collections 模块有一些从 ABC 派生的具体类; 当然,这些还可以进一步推导出来。 此外,collections.abc 子模块有一些 ABC,可用于测试类或实例是否提供特定接口,例如,是否可散列或是否是映射。

该模块提供了用于定义 ABC 的元类 ABCMeta 和用于通过继承交替定义 ABC 的辅助类 ABC

class abc.ABC

具有 ABCMeta 作为其元类的辅助类。 使用这个类,可以通过简单地从 ABC 派生来创建抽象基类,避免有时混淆元类的用法,例如:

from abc import ABC

class MyABC(ABC):
    pass

请注意,ABC 的类型仍然是 ABCMeta,因此从 ABC 继承需要有关元类使用的常规预防措施,因为多重继承可能会导致元类冲突。 也可以通过传递 metaclass 关键字并直接使用 ABCMeta 来定义抽象基类,例如:

from abc import ABCMeta

class MyABC(metaclass=ABCMeta):
    pass

3.4 版中的新功能。

class abc.ABCMeta

用于定义抽象基类 (ABC) 的元类。

使用这个元类来创建一个 ABC。 ABC 可以直接子类化,然后充当混合类。 您还可以将不相关的具体类(甚至内置类)和不相关的 ABC 注册为“虚拟子类”——这些及其后代将被内置 issubclass() 函数视为注册 ABC 的子类,但注册 ABC 不会出现在他们的 MRO(方法解析顺序)中,注册 ABC 定义的方法实现也不会被调用(甚至不能通过 super())。 1

使用 ABCMeta 元类创建的类具有以下方法:

register(subclass)

注册 subclass 作为这个 ABC 的“虚拟子类”。 例如:

from abc import ABC

class MyABC(ABC):
    pass

MyABC.register(tuple)

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

在 3.3 版更改: 返回注册的子类,以允许用作类装饰器。

3.4 版更改: 要检测对 register() 的调用,可以使用 get_cache_token() 函数。

您还可以在抽象基类中覆盖此方法:

__subclasshook__(subclass)

(必须定义为类方法。)

检查 subclass 是否被认为是这个 ABC 的子类。 这意味着您可以进一步自定义 issubclass 的行为,而无需在要考虑 ABC 子类的每个类上调用 register()。 (此类方法是从 ABC 的 __subclasscheck__() 方法调用的。)

此方法应返回 TrueFalseNotImplemented。 如果它返回 True,则 子类 被视为此 ABC 的子类。 如果它返回 False,则 子类 不被视为此 ABC 的子类,即使它通常是一个子类。 如果它返回 NotImplemented,子类检查将继续使用通常的机制。

要演示这些概念,请查看以下示例 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)

ABC MyIterable 将标准可迭代方法 __iter__() 定义为抽象方法。 这里给出的实现仍然可以从子类中调用。 get_iterator() 方法也是 MyIterable 抽象基类的一部分,但它不必在非抽象派生类中被覆盖。

此处定义的 __subclasshook__() 类方法表示,任何在其 __dict__(或其基类之一的方法中)具有 __iter__() 方法的类,通过 __mro__ 列表访问)也被认为是 MyIterable

最后,最后一行使 Foo 成为 MyIterable 的虚拟子类,即使它没有定义 __iter__() 方法(它使用旧式可迭代协议,定义为 __len__()__getitem__())。 请注意,这不会使 get_iterator 作为 Foo 的方法可用,因此单独提供。

abc 模块还提供了以下装饰器:

@abc.abstractmethod

指示抽象方法的装饰器。

使用这个装饰器需要类的元类是 ABCMeta 或者是从它派生的。 一个具有从 ABCMeta 派生的元类的类不能被实例化,除非它的所有抽象方法和属性都被覆盖。 可以使用任何正常的“超级”调用机制来调用抽象方法。 abstractmethod() 可用于声明属性和描述符的抽象方法。

不支持向类动态添加抽象方法,或在方法或类创建后尝试修改其抽象状态。 abstractmethod() 只影响使用常规继承派生的子类; 使用 ABC 的 register() 方法注册的“虚拟子类”不受影响。

abstractmethod() 与其他方法描述符结合使用时,应作为最内层装饰器使用,如下面的使用示例所示:

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

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

为了正确地与抽象基类机器互操作,描述符必须使用 __isabstractmethod__ 将自己标识为抽象。 通常,如果用于组成描述符的任何方法是抽象的,则此属性应为 True。 例如,Python 的内置 属性 相当于:

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

笔记

与 Java 抽象方法不同,这些抽象方法可能有一个实现。 这个实现可以通过覆盖它的类的 super() 机制调用。 在使用协作多重继承的框架中,这可以用作超级调用的端点。

abc 模块还支持以下遗留装饰器:

@abc.abstractclassmethod

3.2 版中的新功能。

自 3.3 版起已弃用:现在可以将 classmethodabstractmethod() 一起使用,使该装饰器变得多余。

内置 classmethod() 的子类,表示抽象类方法。 否则它类似于 abstractmethod()

这种特殊情况已被弃用,因为 classmethod() 装饰器现在在应用于抽象方法时被正确标识为抽象:

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

3.2 版中的新功能。

自 3.3 版起已弃用: 现在可以将 staticmethodabstractmethod() 一起使用,使该装饰器变得多余。

内置 staticmethod() 的子类,表示抽象静态方法。 否则它类似于 abstractmethod()

这种特殊情况已被弃用,因为 staticmethod() 装饰器现在在应用于抽象方法时被正确标识为抽象:

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

自 3.3 版起已弃用:现在可以将 属性property.getter()property.setter()property.deleter()抽象方法一起使用(),使这个装饰器变得多余。

内置 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):
        ...

abc 模块还提供以下功能:

abc.get_cache_token()

返回当前抽象基类缓存令牌。

令牌是一个不透明的对象(支持相等性测试),用于标识虚拟子类的抽象基类缓存的当前版本。 在任何 ABC 上每次调用 ABCMeta.register() 时,令牌都会发生变化。

3.4 版中的新功能。

脚注

1
C++ 程序员应该注意 Python 的虚拟基类概念与 C++ 的不同。