资讯专栏INFORMATION COLUMN

Python基础之接口——从协议到抽象基类

TwIStOy / 3125人阅读

摘要:本文重点协议是中非正式的接口了解抽象基类的基本概念以及标准库中的抽象基类掌握抽象基类的使用方法。三抽象基类的使用通过继承声明抽象基类声明抽象基类最简单的方式是继承或其他抽象基类注意在之间,继承抽象基类的语法是。

导语:本文章记录了本人在学习Python基础之面向对象篇的重点知识及个人心得,打算入门Python的朋友们可以来一起学习并交流。

本文重点:

1、协议是Python中非正式的接口;
2、了解抽象基类的基本概念以及标准库中的抽象基类;
3、掌握抽象基类的使用方法。
一、协议的高度动态本性 1、协议与接口的基本概念

协议:是Python中非正式的接口,是令Python这种动态类型语言实现多态的方式。
接口:泛指实体把自己提供给外界的一种抽象化物(可以为另一实体),用以由内部操作分离出外部沟通方法,使其能被内部修改而不影响外界其他实体与其交互的方式。
类的接口:类实现或继承的公开属性(方法或数据属性),包括特殊方法,如__getitem__或__add__。

2、协议是非正式的

协议是非正式的,只由文档和约定定义,不具备强制性。
以序列协议为例,假设我们想实现迭代以及in运算,通常需要__iter__和__contains__方法,但事实上只实现__getitem__方法也可以。原因在于当Python发现没有__iter__和__contains__可用时,会转而调用__getitem__方法设法让迭代和in运算符可用。
小结:部分实现协议是有用的。

3、使用猴子补丁在运行时实现协议

在运行时修改类或模块而不改动源码,从而实现目标协议接口的操作就是打猴子补丁。

二、抽象基类 1、基本概念

鸭子类型(duck typing):不关注对象的类型,而是关注对象具有的行为(方法)。鸭子类型像多态一样工作,但是没有继承。
在鸭子类型中,协议风格的接口与继承完全没有关系,实现同一个协议的各个类是相互独立的。

白鹅类型(goose typing):只要cls是抽象基类,即cls的元类是abc.ABCMeta,就可以使用isinstance(obj,cls)。

抽象基类(abstract base class,ABC):抽象基类就是类里定义了纯虚成员函数的类。纯虚函数只提供了接口,并没有具体实现。抽象基类不能被实例化(不能创建对象),通常是作为基类供子类继承,子类中重写虚函数,实现具体的接口。简言之,ABC描述的是至少使用一个纯虚函数的接口,从ABC派生出的类将根据派生类的具体特征,使用常规虚函数来实现这种接口。

2、标准库中的抽象基类

(1)collections.abc中抽象基类
collections.abc模块中各个抽象基类的UML类图如下所示:

Iterable、 Container 和 Sized
各个集合应该继承这三个抽象基类, 或者至少实现兼容的协议。
Iterable 通过 __iter__ 方法支持迭代;
Container 通过__contains__ 方法支持 in 运算符;
Sized 通过 __len__ 方法支持len() 函数。

Sequence、 Mapping 和 Set
这三个是主要的不可变集合类型, 而且各自都有可变的子类。

MappingView
在 Python 3 中, 映射方法 .items()、 .keys() 和 .values() 返回的对象分别是 ItemsView、 KeysView 和 ValuesView 的实例。 前两个类还从 Set 类继承了丰富的接口,涉及集合的全部运算符。

Callable 和 Hashable
这两个抽象基类与集合没有太大的关系,只不过因为collections.abc 是标准库中定义抽象基类的第一个模块, 而它们又太重要了,因此才把它们放到 collections.abc 模块中。Callable 或 Hashable 的子类非常少见。这两个抽象基类的主要作用是为内置函数 isinstance 提供支持,以一种安全的方式判断对象能不能调用或散列。

Iterator
是 Iterable 的子类。

(2)numbers包中的数字塔
按照自上而下的线性结构,Number是位于最顶端的超类,详细排序如下:

Number

Complex

Real

Rational

Integral

例如,检查一个数是否是整数,可以使用isinstance(x,numbers.Integral)。

三、抽象基类的使用 1、通过继承声明抽象基类

声明抽象基类最简单的方式是继承abc.ABC或其他抽象基类:Class Student(abc.ABC)
注意:在Python3.0~3.3之间,继承抽象基类的语法是:Class Student(metaclass=abc.ABCMeta)。

2、判断子类是否符合接口定义

在定义抽象基类的子类时,子类需要将继承的抽象基类中的抽象方法具体实现。

3、声明虚拟子类实现抽象基类的接口

虚拟子类:指的是不通过继承而利用注册把一个类变成抽象基类的子类。
注册虚拟之类的方式是调用register方法,语法是@抽象基类名称.register。
经注册后的虚拟子类可以被issubclass和isinstance等函数识别,但是注册的类不会从抽象基类中继承任何方法或属性。具体可通过类属性__mro__查看类的真实继承关系。

四、其它

1、抽象基类中声明抽象类方法需要使用@abc.abstractmethod标记,并且在@abc.abstractmethod和def之间不能有其他装饰器。
2、内省类的继承关系的方法:
__subclasses__():返回类的直接子类列表,不含虚拟子类。
__abcregistry:抽象基类独有的属性,是抽象类注册的虚拟子类的弱引用。
3、__subclasshook__:令抽象基类识别没有进行子类化和注册的类,此方法在abc.Sized中有应用。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/41315.html

相关文章

  • Python学习路30-接口协议抽象基类

    摘要:本篇内容将从鸭子类型的动态协议,逐渐过渡到使接口更明确能验证实现是否符合规定的抽象基类。抽象基类介绍完动态实现接口后,现在开始讨论抽象基类,它属于静态显示地实现接口。标准库中的抽象基类从开始,标准库提供了抽象基类。 《流畅的Python》笔记。本篇是面向对象惯用方法的第四篇,主要讨论接口。本篇内容将从鸭子类型的动态协议,逐渐过渡到使接口更明确、能验证实现是否符合规定的抽象基类(Abst...

    LucasTwilight 评论0 收藏0
  • 流畅的python读书笔记-第11章-接口协议抽象基类

    摘要:自己定义的抽象基类要继承。抽象基类可以包含具体方法。这里想表达的观点是我们可以偷懒,直接从抽象基类中继承不是那么理想的具体方法。 抽象基类 抽象基类的常见用途: 实现接口时作为超类使用。 然后,说明抽象基类如何检查具体子类是否符合接口定义,以及如何使用注册机制声明一个类实现了某个接口,而不进行子类化操作。 如何让抽象基类自动识别任何符合接口的类——不进行子类化或注册。 接口在动态类...

    Kyxy 评论0 收藏0
  • Python中继承的优缺点

    摘要:本文重点不要试图在内置类型的子类中重写方法,可以继承的可拓展类寻求变通掌握多重继承中的和了解处理多重继承的一些建议。子类化的代码如下输出小结上述问题只发生在语言实现的内置类型子类化情况中,而且只影响直接继承内置类型的自定义类。 导语:本文章记录了本人在学习Python基础之面向对象篇的重点知识及个人心得,打算入门Python的朋友们可以来一起学习并交流。 本文重点: 1、不要试图在内置...

    Sourcelink 评论0 收藏0
  • [Python3]Python面向对象的程序设计

    摘要:于发表了著名的有害论的论文引起了长达数年的论战并由此产生了结构化程序设计方法。到现在为止面向对象已经成为了主流的开发思想。面向对象的程序设计优点解决了程序的扩展性。 [Python3]Python面向对象的程序设计 一、面向对象的程序设计的由来 1.第一阶段:面向机器,1940年以前 最早的程序设计都是采用机器语言来编写的,直接使用二进制码来表示机器能够识别和执行的指令和数据。 简单来...

    OpenDigg 评论0 收藏0
  • Python学习路25-使用一等函数实现设计模式

    摘要:本篇主要讲述中使用函数来实现策略模式和命令模式,最后总结出这种做法背后的思想。 《流畅的Python》笔记。本篇主要讲述Python中使用函数来实现策略模式和命令模式,最后总结出这种做法背后的思想。 1. 重构策略模式 策略模式如果用面向对象的思想来简单解释的话,其实就是多态。父类指向子类,根据子类对同一方法的不同重写,得到不同结果。 1.1 经典的策略模式 下图是经典的策略模式的U...

    econi 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<