python await 回调判断_from yield to await——Python协程演进过程(三)

这一part专讲yield from 语法。在前一篇文章中,我们实现了一个协程版的生产者消费者,在上一篇文章中,需要使用异常机制来返回消费者函数的值。这种写法是非常讨厌的,在python中,可以使用yield from来简化这种写法。

in运算符

在python中,如果在对象的表现上需要实现一些新的动作,就会用到内置的魔法方法,也就是那些被双下划线包裹的方法。比如让自定义类型的对象实现加运算,只需要重写该自定义对象的__add__方法。

在python中除了+运算符这些常见的运算符,python还实现了in运算符。把这一运算符作为关键词在其他语言里很少见到。这一设计,使得判断“对象是否处于集合中”这种动作只需要一个if语句,而且还让for循环的可读性提升了一个level。而一个对象只要实现了迭代器相关的魔法方法,就支持in运算,协程也支持。

yield from新语法

在协程的调用方,一个简化版的调用往往长这样子:

for v in g:

yield v

而新语法做的一个工作就是将上述代码实现的功能用一个新语法yield from代替,最终能完成这样的操作:

RESULT = yield from EXPR

实现yield from语法的伪代码如下:

_i = iter(EXPR)

try:

_y = next(_i)

except StopIteration as _e:

_r = _e.value

else:

while 1:

try:

_s = yield _y

except StopIteration as _e:

_r = _e.value

break

RESULT = _r

上述代码只包含了send方法的处理,不包含其他方法和异常的处理。其所做的工作就是当遇到StopIteration 时,就把异常中的value作为结果返回。这一语法,既能将send发送的值从外部传递到内部,又能将返回值从内部传回外部。

理解了这一点,看下面这张图就很容易了,这张图的具体解释可以看fluent python第16章。这里简单的讲所完成的功能就是,通过yield from将子生成器的控制权,从子作用域传递到上层作用域。

这段代码包含三个部分。子生成器:一个用于计算移动平均值的函数,用yield接收send发送过来的值,return返回累加之后的结果。

委派生成器:一个while循环将yield from通道的结果保存到上层传入的results字典中,yield from是可暂停的。

调用方:next预激,send发送值,send(None)结束。

yield from的语法的出现不仅仅是为了简化for+in+yield的语法糖,实质上的作用是将生成器的控制权,也就是send等方法的调用与返回,在不同层次的作用域之间传递。而协程的关键点也在于控制权的让渡,这些花式玩法本质上是在折腾控制权这个事,具体而言就是决定让哪部分代码占用当前CPU。

基于协程的事件驱动型框架

对于一个事件驱动型框架而言,至少要有这三个东西外层要有个loop,负责各种底层操作的调度,具体的操作就是调用send这些方法。

中层是控制权传递的语法,yield到await都是在干这事。

底层有个有个协程函数,无论是Future还是Event对象,都能通过相应的方法让渡出控制权。

所有现在的各种框架,在最后执行协程的时候,多数操作都是将一个协程的函数体(而不是函数的实例),传递给一个loop执行,和map方法一样一样的。

协程的意义

协程这个东西可以看成用户控制的线程,这里的用户控制是区别于真实的由硬件控制并切换上下文的线程。协程可以以同步的方式写异步非抢占式代码,代码逻辑更人性化,没有新语法时,python中是靠tornado和gevent等库来实现这一目的。

如果不用协程,这种控制流一般用回调函数的方式来写。而在python这种靠缩进判断代码块的语言,用回调写起来真是要死要死。就算JavaScript,也不应该嵌套太多,不服你看下图。

至此,我们基本了解了yield from的前身今世,这个语法在python3.5被await关键字替代,经过这一系列的花式操作,python完成了对协程的原生支持。下一章讲await做个收尾,可能要等到很久之后了。

PS:

说实话,这一系列写下来我是不满意的。本意是想通过协程语法的改进来把有关知识点串起来,希望读者老爷们读下来能有一个恍然大悟的感觉,现在看来是达不到了。文章结构和内容都没达到我想要的目的,可能我理解是理解了,表达出来又是一回事。不过,在写的过程中我自己倒是又学到不少,括弧笑。总之还是先发出来,等以后水平上去了,再回过头来改吧。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值