Python协程演进过程

Milestone

协程相关的关键字和方法的引入:

Python 2.2(2001年)yield

Python 2.5(2006年) .send() .throw() .close()

Python 3.3(2012年) yield from Python 3.5(2015年)async await

Duck type

在面向对象的支持上,C++采用了多重继承等一系列C++风格的东西,Java是单继承+接口,JavaScript之前是Prototype,而Python采用了多继承+duck type,并用super来安全的初始化父类。而同样喜欢宣传自己优雅的设计的Ruby也是采用的Duck Type。

什么是Duck Type

当我看到一只鸟走路像鸭子,游泳像鸭子,叫声像鸭子,那我就把它叫做鸭子。(When I see a bird that walks like a duck and swims like a duck and quacks like a duck, I call that bird a duck.)

简而言之就是,判断一个对象的类型不是看他爸爸是谁,而是他实现了什么方法。 举个例子:

>>> class Foo:

...     def __iter__(self):

...             pass

...

>>> from collections import Iterable

>>> isinstance(Foo(),Iterable)

True

在命令行里运行如上代码,会发现Foo类并没有继承任何迭代相关的父类,但却被认为是可迭代对象。正是由于Duck Type,避免了复杂的继承关系。

Iterator

解释器在判断要给对象是否是可迭代对象时,是这么做的:

 判断是否有__iter__,获取一个迭代器。

    实现了__getitem__,创建一个迭代器,按索引获取元素。

    不满足以上条件则对象不可迭代,抛出异常。

可迭代对象的UML图如下:

通过iter方法返回一个迭代器,而迭代器需要实现一个next方法和iter方法。

Generators

生成器是为了满足惰性加载而出现的,比如一些数据在使用时才生产出来,而不是初始化时就加载到内存里了。在编程中,英文含有lazy的相关专业词汇大多都是这样的作用。

在python中,一个函数中如果有yield关键词,那么这个函数就是个生成器函数,该函数调用时会立即返回一个生成器对象,而不是函数结果。而要获取该函数产出的结果,需要调用next方法(根据不同版本,有的是双下划线版本的next方法)。

协程的定义是,一个可以随时挂起并让出CPU控制权的控制流。惰性加载在协程中的意义在于,可以通过将未来的控制流放在next方法中,使得程序暂时让出CPU,在需要时通过send方法转进回来。

Summary

Python的Duck Type保证了一种灵活的面向对象实践。

在迭代器基础上实现了惰性加载的生成器,之后为了完善生成器,提供了send等方法,和原有的next方法配合,是实现协程的基础。

原文发布于微信公众号 - Python中文社区(python-china)

原文发表时间:2017-06-28

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏JAVA高级架构

Java面试2018常考题目汇总(一)

一、JAVA基础篇-概念 1.简述你所知道的Linux: Linux起源于1991年,1995年流行起来的免费操作系统,目前, Linux是主流的服务器操作系统...

355100
来自专栏用户2442861的专栏

Python中GBK, UTF-8和Unicode的编码问题

编码问题,一直是使用python2时的一块心病。几乎所有的控制台输入输出、IO操作和HTTP操作都会涉及如下的编码问题:

24310
来自专栏闻道于事

问题整理

  相关子查询,无关子查询 所谓相关子查询,是指求解相关子查询不能像求解普通子查询那样,一次将子查询求解出来,然后求解父查询。相关子查询的内层查询由于与外层查询...

30440
来自专栏互联网杂技

前端--理解 Promise 的工作原理

Javascript 采用回调函数(callback)来处理异步编程。从同步编程到异步回调编程有一个适应的过程,但是如果出现多层回调嵌套,也就是我们常说的厄运的...

37860
来自专栏测试开发架构之路

C语言之预处理命令与用typedef命名已有类型

 预处理命令 主要是改进程序设计环境,以提高编程效率,不属于c语言本身的组成部分,不能直接对它们进行编译,必须在对 程序编译之前,先对程序中的这些特殊命令进行...

42690
来自专栏码云1024

python简明笔记

通过 for 语句我们可以使用 for 循环。Python 里的 for 循环与 C 语言中的不同。这里的 for 循环遍历任何序列(比如列表和字符串)中的每一...

62090
来自专栏菩提树下的杨过

python:函数中五花八门的参数形式(茴香豆的『回』字有四种写法)

28540
来自专栏Golang语言社区

Golang语言之异常处理

在编写Go语言代码的时候,我们应该习惯使用error类型值来表明非正常的状态。作为惯用法,在Go语言标准库代码包中的很多函数和方法也会以返回error类型值来表...

358130
来自专栏信安之路

python 2.7正则下篇

看的出来(?P<year>\d{4})中,可以用尖括号中的名字去获取后面正则匹配出来的数值,这样方便调用,便于记忆。

8920
来自专栏JavaEdge

Java语法糖1 泛型与类型擦除

38670

扫码关注云+社区

领取腾讯云代金券