首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

abc

2.6版本中的新功能。

源代码: Lib / abc.py

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

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

该模块提供以下类:

class abc.ABCMeta

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

使用这个元类来创建一个ABC。ABC可以直接分类,然后作为混合课。您也可以将不相关的具体类(甚至内置类)和不相关的ABCs注册为“虚拟子类” - 这些及其后代将被内置issubclass()函数视为注册ABC的子类,但注册ABC不会显示(方法解析顺序),注册ABC定义的方法实现也不会被调用(甚至不能super())。[1]

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

register(subclass)

子类 注册为此ABC的“虚拟子类”。例如:

代码语言:javascript
复制
from abc import ABCMeta

class MyABC:
    __metaclass__ = ABCMeta

MyABC.register(tuple)

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

您也可以在抽象基类中重写此方法:

__subclasshook__(subclass)

(必须定义为类方法。)

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

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

为了演示这些概念,请看这个ABC定义的例子:

代码语言:javascript
复制
class Foo(object):
    def __getitem__(self, index):
        ...
    def __len__(self):
        ...
    def get_iterator(self):
        return iter(self)

class MyIterable:
    __metaclass__ = ABCMeta

    @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__(或其基类之一,通过__mro__列表访问)中具有__iter __()方法的类也被视为MyIterable。

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

它还提供了以下装饰器:

abc.abstractmethod(function)

指示抽象方法的装饰器。

使用这个装饰器需要该类的元类是ABCMeta或从它派生。 除非所有抽象方法和属性都被覆盖,否则不能实例化具有派生自ABCMeta的元类的类。 抽象方法可以使用任何普通的“超级”调用机制来调用。

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

用法:

代码语言:javascript
复制
class C:
    __metaclass__ = ABCMeta
    @abstractmethod
    def my_abstract_method(self, ...):
        ...

注意

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

abc.abstractproperty([fget[, fset[, fdel[, doc]]]])

内置的子类property(),表示抽象属性。

使用这个函数需要该类的元类是ABCMeta或从它派生。 除非所有抽象方法和属性都被覆盖,否则不能实例化具有派生自ABCMeta的元类的类。 抽象属性可以使用任何普通的“超级”调用机制来调用。

用法:

代码语言:javascript
复制
class C:
    __metaclass__ = ABCMeta
    @abstractproperty
    def my_abstract_property(self):
        ...

这定义了一个只读属性; 你也可以使用'long'属性声明来定义一个读写抽象属性:

代码语言:javascript
复制
class C:
    __metaclass__ = ABCMeta
    def getx(self): ...
    def setx(self, value): ...
    x = abstractproperty(getx, setx)

脚注

1

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

扫码关注腾讯云开发者

领取腾讯云代金券