5)协程二(yeild from)
一:yield from说明
python从3.3版本开始使用yield from 替代yield
yield from 结构会在内部自动捕获 StopIteration 异常。
这种处理方式与 for 循环处理 StopIteration 异常的方式一样:循环机制使用用户易于理解的方式处理异常。
对 yield from 结构来说,解释器不仅会捕获 StopIteration 异常,还会把value 属性的值变成 yield from 表达式的值。
yield from x 表达式对 x 对象所做的第一件事是,调用 iter(x),从中获取迭代器。
因此, x 可以是任何可迭代的对象可是,如果 yield from 结构唯一的作用是替代产出值的嵌套 for 循环,这个结构很有可能不会添加到 Python 语言中。
yield from 的主要功能是打开双向通道,把最外层的调用方与最内层的子生成器连接起来,
这样二者可以直接发送和产出值,还可以直接传入异常,而不用在位于中间的协程中添加大量处理异常的样板代码。
有了这个结构,协程可以通过以前不可能的方式委托职责。
PEP 380 使用了一些专门的术语
#委派生成器
包含 yield from <iterable> 表达式的生成器函数。
#子生成器
从 yield from 表达式中 <iterable> 部分获取的生成器
委派生成器在 yield from 表达式处暂停时,调用方可以直接把数据发给子生成器,子生成器再把产出的值发给调用方。
子生成器返回之后,解释器会抛出
异常,并把返回值附加到异常对象上,此时委派生成器会恢复
二:示例
示例:使用 yield from 计算平均值并输出统计报告
# _*_ coding:utf-8 _*_
__author__ = "lixiang"
from collections import namedtuple
Result = namedtuple('Result', 'count average') # 子生成器
def averager(): #
total = 0.0
count = 0
average = None
while True:
term = yield #
if term is None:#
break
total += term
count += 1
average = total/count
return Result(count, average) # # 委派生成器
def grouper(results, key): #
while True: #
results[key] = yield from averager() # # 客户端代码,即调用方
def main(data): #
results = {}
for key, values in data.items():
group = grouper(results, key) #
next(group) #
for value in values:
group.send(value) #
group.send(None) # 重要!#12
# print(results) # 如果要调试,去掉注释
report(results)
# 输出报告
def report(results):
for key, result in sorted(results.items()):
group, unit = key.split(';')
print('{:2} {:5} averaging {:.2f}{}'.format(result.count, group, result.average, unit)) data = {
'girls;kg':
[40.9, 38.5, 44.3, 42.2, 45.2, 41.7, 44.5, 38.0, 40.6, 44.5],
'girls;m':
[1.6, 1.51, 1.4, 1.3, 1.41, 1.39, 1.33, 1.46, 1.45, 1.43],
'boys;kg':
[39.0, 40.8, 43.2, 40.8, 43.1, 38.6, 41.4, 40.6, 36.3],
'boys;m':
[1.38, 1.5, 1.32, 1.25, 1.37, 1.48, 1.25, 1.49, 1.46],
}
if __name__ == '__main__':
main(data) """
❶ 的 averager 协程一样。这里作为子生成器使用。
❷ main 函数中的客户代码发送的各个值绑定到这里的 term 变量上。
❸ 至关重要的终止条件。如果不这么做,使用 yield from 调用这个协程的生成器会永
远阻塞。
❹ 返回的 Result 会成为 grouper 函数中 yield from 表达式的值。
❺ grouper 是委派生成器。
❻ 这个循环每次迭代时会新建一个 averager 实例;每个实例都是作为协程使用的生成
器对象。
❼ grouper 发送的每个值都会经由 yield from 处理,通过管道传给 averager 实
例。 grouper 会在 yield from 表达式处暂停,等待 averager 实例处理客户端发来的
值。 averager 实例运行完毕后,返回的值绑定到 results[key] 上。 while 循环会不断
创建 averager 实例,处理更多的值。
❽ main 函数是客户端代码,用 PEP 380 定义的术语来说,是“调用方”。这是驱动一切的
函数。
❾ group 是调用 grouper 函数得到的生成器对象,传给 grouper 函数的第一个参数是
results,用于收集结果;第二个参数是某个键。 group 作为协程使用。
❿ 预激 group 协程。
⓫ 把各个 value 传给 grouper。传入的值最终到达 averager 函数中 term = yield 那
一行; grouper 永远不知道传入的值是什么。
⓬ 把 None 传入 grouper,导致当前的 averager 实例终止,也让 grouper 继续运行,
再创建一个 averager 实例,处理下一组值。
5)协程二(yeild from)的更多相关文章
- Python自动化开发 -进程、线程和协程(二)
本节内容 一.线程进程介绍 二. 线程 1.线程基本使用 (Threading) 2.线程锁(Lock.RLock) 3.信号量(Semaphore) 4.事件(event) 5.条件(Conditi ...
- Python异步IO之协程(二):使用asyncio的不同方法实现协程
引言:在上一章中我们介绍了从yield from的来源到async的使用,并在最后以asyncio.wait()方法实现协程,下面我们通过不同控制结构来实现协程,让我们一起来看看他们的不同作用吧- 在 ...
- python协程和yeild
python多线程其实在操作系统级别是进程,因为在执行时,默认加了一个全局解释器锁(GIL),python的多线程,本质还是串行的,无法利用多核的优势:在java和C# 中,多线程是并发的,可以充分利 ...
- Kotlin Coroutine(协程): 二、初识协程
@ 目录 前言 一.初识协程 1.runBlocking: 阻塞协程 2.launch: 创建协程 3.Job 4.coroutineScope 5.协程取消 6.协程超时 7.async 并行任务 ...
- 011-Python-进程、线程于协程
1.进程与线程 进程: 一个程序要运行时所需的所有资源的集合: 一个进程至少需要一个线程,这个线程称为主线程,一个进程里可以包含多个线程: cpu 核数越多,代表着你可以真正并发的线程越多2个进程之间 ...
- Golang 协程调度
一.线程模型 N:1模型,N个用户空间线程在1个内核空间线程上运行.优势是上下文切换非常快但是无法利用多核系统的优点. 1:1模型,1个内核空间线程运行一个用户空间线程.这种充分利用了多核系统的优势但 ...
- Python_oldboy_自动化运维之路_线程,进程,协程(十一)
本节内容: 线程 进程 协程 IO多路复用 自定义异步非阻塞的框架 线程和进程的介绍: 举个例子,拿甄嬛传举列线程和进程的关系: 总结:1.工作最小单元是线程,进程说白了就是提供资源的 2.一个应用程 ...
- (17) go 协程管道
一.协程 二.管道
- python协程详解
目录 python协程详解 一.什么是协程 二.了解协程的过程 1.yield工作原理 2.预激协程的装饰器 3.终止协程和异常处理 4.让协程返回值 5.yield from的使用 6.yield ...
随机推荐
- 使用jQuery插件时避免重复引入jquery.js文件
当一个页面使用多个jQuery插件时,需要避免重复引入jquery.js文件,因为后面映入的jQuery.js文件中定义的jQuery对象会覆盖掉前面的jQuery对象,导致之前定义的jQuery插件 ...
- Listener 快速开始
[SessionListener] @WebListenerpublic class SessionListener implements HttpSessionListener,HttpSessio ...
- mysql插入记录INSERT与多表更新
1.第一种:INSERT [INTO] tbl_name[ (col_name, ... ) ] {VALUES | VALUE}({expr |default}, ... ), (...), .. ...
- Andrew NG 机器学习编程作业5 Octave
问题描述:根据水库中蓄水标线(water level) 使用正则化的线性回归模型预 水流量(water flowing out of dam),然后 debug 学习算法 以及 讨论偏差和方差对 该线 ...
- bus实现兄弟组件传值
传递的地方:两个组件都要引入这个公共的bus中转函数 Bus.js文件相当于一个公共的对象: 传递的文件中写入这个方法: 兄弟组件通过点击事件输出参数,需要的组件来接收传递过来的参数:
- 2.4 if-else
if-else 想一想:在使用if的时候,它只能做到满足条件时要做的事情.那万一需要在不满足条件的时候,做某些事,该怎么办呢? 答:使用 if-else <1>if-else的使用格式 i ...
- PHP7语法知识(一):语言基础
一.数据类型 1.字符串: 2.整形: var_dump函数:返回变量的数据类型和值. 3.浮点型: 4.布尔型: 5.数组: 6.对象: 7.NULL值 二.运算符 1.算术运算符: 2.递增递减运 ...
- python 多线程小方法
import time from multiprocessing import Process, Lock, JoinableQueue from multiprocessing import Sem ...
- angular-file-upload 项目实践踩坑
API文档: https://github.com/nervgh/angular-file-upload/wiki/Module-API 过程中得到昊哥的鼎力帮助,感谢. 需求如下,分别选择多个文件, ...
- B - Tree Rotations HYSBZ - 2212 (线段树合并)
题目链接:https://cn.vjudge.net/contest/287725#problem/B 题目大意:现在有一棵二叉树,所有非叶子节点都有两个孩子.在每个叶子节点上有一个权值(有n个叶子节 ...