上一话题

contextlib — 实用程序为 with 语句上下文

下一话题
就业培训     下载中心     Wiki     联络
登录   注册

Log
  1. 首页
  2. Python 3.12.4
  3. 索引
  4. 模块
  5. 下一
  6. 上一
  7. Python 标准库
  8. Python 运行时服务
  9. abc — 抽象基类

abc — 抽象基类 ¶

源代码: Lib/abc.py


本模块提供基础设施为定义 抽象基类 (ABC) 在 Python 中,如提纲于 PEP 3119 ;见 PEP 了解为什么要把这添加到 Python (另请参阅 PEP 3141 和 numbers 模块关于基于 ABC 的数字类型层次结构)。

The collections 模块有一些派生自 ABC (抽象基类) 的具体类;当然,这些可以进一步派生。此外, 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 映射 .

本模块提供元类 ABCMeta 为定义 ABC (抽象基类) 和帮手类 ABC 以透过继承另外定义 ABC (抽象基类):

class abc. ABC (抽象基类) ¶

帮手类拥有 ABCMeta 如其元类。采用此类,可以创建抽象基类通过简单派生自 ABC 避免有时令人困惑的元类用法,例如:

from abc import ABC
class MyABC(ABC):
    pass
												

注意,类型对于 ABC 仍然是 ABCMeta ,因此继承自 ABC 要求通常不管元类用法的预防措施,由于多继承可能导致元类冲突。定义抽象基类还可以通过传递元类关键词并使用 ABCMeta 直接,例如:

from abc import ABCMeta
class MyABC(metaclass=ABCMeta):
    pass
												

Added in version 3.4.

class abc. ABCMeta ¶

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

使用此元类能创建 ABC (抽象基类)。可以直接子类化 ABC,然后充当混合类。还可以把不相关具体类 (甚至是内置类) 和不相关 ABC 注册成 "虚拟子类" – 将把这些类及它们的后代认为是注册 ABC 的子类通过内置 issubclass() 函数,但注册的 ABC 既不会出现在它们的 MRO (方法分辨次序) 中,由注册的 ABC 定义的方法实现也不可调用 (甚至无法透过 super() ). [ 1 ]

类创建采用元类化的 ABCMeta 拥有以下方法:

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 版改变: 要检测调用 register() ,可以使用 get_cache_token() 函数。

也可以覆盖抽象基类中的此方法:

__subclasshook__ ( 子类 ) ¶

(必须定义成类方法)。

校验是否 subclass 被认为是此 ABC 的子类。这意味着可以定制行为若 issubclass() 进一步不需要调用 register() 对于想要考虑子类化 ABC 的各类 (调用此类方法是从 __subclasscheck__() 方法对于 ABC)。

此方法应返回 True , False or NotImplemented 。若它返回 True , subclass 被认为是此 ABC 的子类。若它返回 False , subclass 不被认为是此 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 抽象基类,但不必在非抽象派生类覆写它。

The __subclasshook__() 类方法定义在这里说任何类拥有 __iter__() 方法在其 __dict__ (或在其基类,访问凭借 __mro__ 列表) 被认为是 MyIterable 也。

最终,最后行制作 Foo 虚拟子类化的 MyIterable ,即使它没有定义 __iter__() 方法 (使用旧式可迭代协议,其定义在术语 __len__() and __getitem__() )。注意,这不会使 get_iterator 可用作方法对于 Foo ,所以它是单独提供的。

The abc 模块还提供下列装饰器:

@ abc. abstractmethod ¶

指示抽象方法的装饰器。

使用此装饰器要求类的元类是 ABCMeta 或是来自它的派生。拥有元类的类派生自 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() 函数。 abstractmethod() only affects subclasses derived using regular inheritance; “virtual subclasses” registered with the ABC’s register() method are not affected.

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

注意

Unlike Java abstract methods, these abstract methods may have an implementation. This implementation can be called via the super() 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 模块还支持下列传统装饰器:

@ abc. abstractclassmethod ¶

Added in version 3.2.

从 3.3 版起弃用: 现在是可能的使用 classmethod with abstractmethod() ,使此装饰器多余。

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

此特殊情况被弃用,因为 classmethod() 装饰器现被正确识别成抽象当应用到抽象方法时:

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

Added in version 3.2.

从 3.3 版起弃用: 现在是可能的使用 staticmethod with abstractmethod() ,使此装饰器多余。

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

此特殊情况被弃用,因为 staticmethod() 装饰器现被正确识别成抽象当应用到抽象方法时:

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

从 3.3 版起弃用: 现在是可能的使用 property , property.getter() , property.setter() and property.deleter() with abstractmethod() ,使此装饰器多余。

子类化的内置 property() ,指示抽象特性。

此特殊情况被弃用,因为 property() 装饰器现被正确识别成抽象当应用到抽象方法时:

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 模块还提供下列函数:

abc. get_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() on any ABC.

Added in version 3.4.

abc. 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.

返回 cls , to allow usage as a class decorator.

若 cls 不是实例化的 ABCMeta ,什么都不做。

注意

This function assumes that cls ’s superclasses are already updated. It does not update any subclasses.

Added in version 3.10.

脚注

[ 1 ]

C++ programmers should note that Python’s virtual base class concept is not the same as C++’s.

上一话题

contextlib — 实用程序为 with 语句上下文

下一话题

atexit — 退出处理程序

本页

  • 报告 Bug
  • 展示源

快速搜索

键入搜索术语或模块、类、函数名称。

  1. 首页
  2. Python 3.12.4
  3. 索引
  4. 模块
  5. 下一
  6. 上一
  7. Python 标准库
  8. Python 运行时服务
  9. abc — 抽象基类

版权所有  © 2014-2026 乐数软件    

工业和信息化部: 粤ICP备14079481号-1