该模块提供了在Python中定义形象基类(ABC - Abstract Base Class)的根底构造,参考PEP 3119;至于为何将其增加到Python,也能够看看PEP 3141numbers模块无关基于ABC的数字的类层次结构的模块。

容器collections模块具备一些衍生自ABC的具体类。当然,这些能够进一步继承衍生。此外, collections.abc子模块具备一些ABC,可用于测试:类或实例是否提供特定的接口,例如,是否可哈希或是否为映射。

此模块提供ABCMeta用于定义ABC 的元类和帮忙程序类,ABC以通过继承来代替地定义ABC:

classabc.`ABC

具备ABCMeta作为其元类的帮忙程序类。应用此类,能够通过ABC 防止有时混同元数据用法的简略派生来创立形象基类,例如:

from abc import ABCclass MyABC(ABC):    pass

请留神,类型ABC为still ABCMeta,因而从继承继承ABC须要无关元类应用的惯例预防措施,因为多重继承可能会导致元类抵触。也能够通过传递 metaclass 关键字并ABCMeta间接应用来定义形象基类,例如:

from abc import ABCMetaclass 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 ABCclass MyABC(ABC):    passMyABC.register(tuple)assert issubclass(tuple, MyABC)assert isinstance((), MyABC)

在版本3.3中更改:返回注册的子类,以容许用作类装璜器。

在版本3.4中更改:要检测对的调用register(),能够应用该 get_cache_token()性能。

您还能够在形象基类中重写此办法:

__subclasshook__(_子类_)

(必须定义为类办法。)

查看_子类_是否被视为此ABC的子类。这意味着您能够自定义issubclass进一步的行为,而无需调用register()要思考为ABC的子类的每个类。(此类办法是从__subclasscheck__()ABC 的办法中调用的。)

这个办法应该返回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 NotImplementedMyIterable.register(Foo)

ABC MyIterable将规范可迭代办法定义 __iter__()为形象办法。此处给出的实现仍能够从子类中调用。该get_iterator()办法也是MyIterable形象基类的一部分,然而在非形象派生类中不用重写此办法~~~~。

__subclasshook__()此处定义的类办法示意,任何__iter__()在其类__dict__(或通过__mro__列表拜访的基类之一)中具备办法的 类也被视为类MyIterable

最初,即便没有定义方法,最初一行仍是Foo的虚构子类(它应用依照和 定义的新式可迭代协定)。请留神,这不能 作为的办法应用,因而是独自提供的。MyIterable__iter__()__len__()__getitem__()get_iterator`Foo`

abc模块还提供以下装璜器:

@`abc.`abstractmethod[](https://docs.python.org/3/lib... "此定义的永恒链接")

装璜器,批示形象办法。

应用此装璜器要求该类的元类是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的内置性能property等效于:

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

与Java形象办法不同,这些形象办法可能具备实现(Java新版也有接口默认实现)。能够通过super()笼罩它的类中的机制来调用此实现。在应用合作式多重继承的框架中,这可用作超级调用的端点。

abc模块还反对以下新式装璜器:

@`abc.`abstractclassmethod[](https://docs.python.org/3/lib... "此定义的永恒链接")

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版本不举荐应用:当初能够应用propertyproperty.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):        ...

abc模块还提供以下性能:

abc.get_cache_token()

返回以后形象基类缓存令牌。

令牌是一个不通明的对象(反对相等性测试),用于标识虚构子类的形象基类缓存的以后版本。令牌随着ABCMeta.register()在任何ABC上的每次调用而扭转。

3.4版的新性能。

脚注

1个

C++程序员应留神,Python的虚构基类概念与C++不同。