Why Python has abstract base class

栏目: Python · 发布时间: 8年前

内容简介:Why Python has abstract base class

抽象基类(Abstract base classes)并不是 Python 本身的语言特性,而是在标准库中提供了一种支持。关于抽象基类, Python Glossary 中定义如下

Abstract base classes complement duck-typing by providing a way to define interfaces when other techniques like hasattr() would be clumsy or subtly wrong (for example with magic methods). ABCs introduce virtual subclasses, which are classes that don’t inherit from a class but are still recognized by isinstance() and issubclass(); see the abc module documentation. Python comes with many built-in ABCs for data structures (in the collections.abc module), numbers (in the numbers module), streams (in the io module), import finders and loaders (in the importlib.abc module). You can create your own ABCs with the abc module.

一般定义抽象基类可以使用 abc.ABCMeta 这个元类,通过 register() 方法能将不相关的具体类(包含 built-in class)及其他抽象类注册为虚子类(virtual subclasses)。

[virtual subclass 这个概念好像只有在 Python 中有提到] issubclass() 会认为他们之间具有子类关系,但抽象基类并不会出现在被注册类的 MRO 中,也不会调用到抽象基类中定义的方法。当然也可以不用费劲的通过 register() 一个个进行注册,能够通过 __subclasshook__() 来控制 issubclass() 的行为。普通类定义 __subclasshook__()

并不会被触发

This method should return True, False or NotImplemented. If it returns True, the subclass is considered a subclass of this ABC. If it returns False, the subclass is not considered a subclass of this ABC, even if it would normally be one. If it returns NotImplemented, the subclass check is continued with the usual mechanism.

演示代码

In [17]: int.__mro__  
Out[17]: (int, object)

In [18]: bool.__mro__  
Out[18]: (bool, int, object)

In [19]: class A(metaclass=abc.ABCMeta):  
    ...:     pass
    ...:

In [20]: A.register(int)  
Out[20]: int

In [21]: int.__mro__  
Out[21]: (int, object)

In [22]: bool.__mro__  
Out[22]: (bool, int, object)

In [23]: issubclass(int, A)  
Out[23]: True

In [24]: issubclass(bool, A)  
Out[24]: True

通常而言,抽象基类就是定义了一系列子类必须要实现的东西,相当于一种契约,如果没有实现这种契约是不能被实例化的。Python 也是如此,不过这种概念相对而言意义不大,因为 Python 可以通过自省(instrospect)和 EAFP 灵活地判断对象是否满足契约。不过在 Python 中抽象基类还有一个作用,那便是用于 duck-typing 中(Glossary 中也提到抽象基类为 duck-typing 提供了扩充)。在这种编程风格中,并不关注对象的类型,而是关注对象是否具有某些行为。而抽象基类可以看做提供了一系列行为的集合。如果你实现了这些行为,便可以看做是这个抽象基类的 virtual subclass

In [35]: class P:  
    ...:     def __iter__(self):
    ...:         pass
    ...:     def __contains__(self, item):
    ...:         pass
    ...:     
    ...:     

# 触发 Container 的 __subclasshook__
In [36]: issubclass(P, Container)  
Out[36]: True

In [37]: issubclass(P, Iterable)  
Out[37]: True

我们可以通过抽象基类来检测对象是否满足条件,正如 duck-typing 所形容的,实现了 __contains__() 的类型都是 Container; 实现了 __iter__() 的类型都是 Iterable。因此可以进行更友好的行为检测,而不是像下面这样松散的代码

if hasattr(P, '__iter__') and hasattr(P, '__contains__'):  
    pass
# or
if all(map(lambda attr: hasattr(P, attr), ['__iter__', '__contains__'])):  
    pass

Reference

Why use Abstract Base Classes in Python?


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Laravel框架关键技术解析

Laravel框架关键技术解析

陈昊、陈远征、陶业荣 / 电子工业出版社 / 2016-7 / 79.00元

《Laravel框架关键技术解析》以Laravel 5.1版本为基础,从框架技术角度介绍Laravel构建的原理,从源代码层次介绍Laravel功能的应用。通过本书的学习,读者能够了解Laravel框架实现的方方面面,完成基于该框架的定制化应用程序开发。 《Laravel框架关键技术解析》第1章到第4章主要介绍了与Laravel框架学习相关的基础部分,读者可以深入了解该框架的设计思想,学习环......一起来看看 《Laravel框架关键技术解析》 这本书的介绍吧!

HTML 压缩/解压工具
HTML 压缩/解压工具

在线压缩/解压 HTML 代码

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

随机密码生成器
随机密码生成器

多种字符组合密码