yield-from示例
#!/usr/bin/python3
# -*- coding: utf-8 -*-
# @Time : 2018/6/20 9:13
# @File : yield_from11.py
from collections import namedtuple
Result = namedtuple('Result', 'count average')
# 子生成器
def averager():
total = 0.0
count = 0
average = None
while True:
# main 函数发送数据到这里
term = yield
if term is None: # 终止条件
break
total += term
count += 1
average = total / count
return Result(count, average) # 返回的Result 会成为grouper函数中yield from表达式的值
# 委派生成器
def grouper(results, key):
# 这个循环每次都会新建一个averager实例,每个实例都是作为协程使用的生成器对象
while True:
# grouper 发送的每个值都会经由yield from 处理,通过管道传给 averager
# grouper 会在yield from表达式处暂停,等待 averager 实例处理客户端发来的值。
# averager 实例运行完毕后,返回的值绑定到results[key] 上。
# while 循环会不断创建 averager 实例,处理更多的值。
results[key] = yield from averager()
# 调用方
def main(data):
results = {}
for key, values in data.items():
# group 是调用grouper函数得到的生成器对象,传给grouper 函数的第一个参数是results,用于收集结果;第二个是某个键
group = grouper(results, key)
next(group)
for value in values:
# 把各个value传给grouper 传入的值最终到达averager函数中
# grouper并不知道传入的是什么,同时grouper实例在yield from处暂停
group.send(value)
# 把None传入groupper,传入的值最终到达averager函数中,导致当前实例终止。然后继续创建下一个实例。
# 如果没有group.send(None),那么averager子生成器永远不会终止,委派生成器也永远不会在此激活,也就不会为result[key]赋值
group.send(None)
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))
print('{:2} {:5} averaging {:.2f}{}'.format(result.count, group, result.average, unit))
# print(result, type(result)) # Result(count=6, average=54.0) <class '__main__.Result'>
data = {
'girls;kg': [40, 41, 42, 43, 44, 54],
'girls;m': [1.5, 1.6, 1.8, 1.5, 1.45, 1.6],
'boys;kg': [50, 51, 62, 53, 54, 54],
'boys;m': [1.6, 1.8, 1.8, 1.7, 1.55, 1.6],
}
if __name__ == '__main__':
main(data)
'''
这段代码从一个字典中读取男生和女生的身高和体重。然后把数据传给之前定义的 averager 协程,最后生成一个报告。
执行结果为
6 boys averaging 54.00kg
6 boys averaging 1.68m
6 girls averaging 44.00kg
6 girls averaging 1.58m
这断代码展示了yield from 结构最简单的用法。委派生成器相当于管道,所以可以把任意数量的委派生成器连接在一起---一个委派生成器使用yield from 调用一个子生成器,
而那个子生成器本身也是委派生成器,使用yield from调用另一个生成器。最终以一个只是用yield表达式的生成器(或者任意可迭代对象)结束。
'''
yield from 的意义
PEP380 分6点说明了yield from 的行为。
子生成器产出的值都直接传给委派生成器的调用方(客户端代码)
使用send() 方法发给委派生成器的值都直接传给子生成器。如果发送的值是None,那么会调用子生成器的 __next__()方法。如果发送的值不是None,那么会调用子生成器的send()方法。如果调用的方法抛出StopIteration异常,那么委派生成器恢复运行。任何其他异常都会向上冒泡,传给委派生成器。
生成器退出时,生成器(或子生成器)中的return expr 表达式会触发 StopIteration(expr) 异常抛出。
yield from表达式的值是子生成器终止时传给StopIteration异常的第一个参数。
传入委派生成器的异常,除了 GeneratorExit 之外都传给子生成器的throw()方法。如果调用throw()方法时抛出 StopIteration 异常,委派生成器恢复运行。StopIteration之外的异常会向上冒泡。传给委派生成器。
如果把 GeneratorExit 异常传入委派生成器,或者在委派生成器上调用close() 方法,那么在子生成器上调用close() 方法,如果他有的话。如果调用close() 方法导致异常抛出,那么异常会向上冒泡,传给委派生成器;否则,委派生成器抛出 GeneratorExit 异常。
yield-from示例的更多相关文章
- python yield 使用示例
1.yield由于创建迭代器 def deal(): tmp = [] for i in range(20): tmp.append(i) if i % 4 == 0: yield tmp tmp = ...
- PHP生成器yield使用示例
<?php function getLines($file) { $f = fopen($file, 'r'); try { while ($line = fgets($f)) { yield ...
- 第十三天python3 生成器yield
生成器generator 生成器指的是生成器对象,可由生成器表达式得到,也可以使用yield关键字得到一个生成器函数,调用这个函数得到一个生成器对象: 生成器函数 函数体中包含yield语句的函数,返 ...
- python基础-迭代器和生成器
一.递归和迭代 1.递归:(问路示例) 递归算法是一种直接或者间接地调用自身算法的过程.在计算机编写程序中,递归算法对解决一大类问题是十分有效的,它往往使算法的描述简洁而且易于理解. 2.迭代:简单理 ...
- ylbtech-LanguageSamples-Yield
ylbtech-Microsoft-CSharpSamples:ylbtech-LanguageSamples-Yield 1.A,示例(Sample) 返回顶部 “Yield”示例 本示例演示如何创 ...
- Scala入门 【1】
Scala入门 [1] 转载请注明出处:http://www.cnblogs.com/BYRans/ 1 基础 val定义的为常量,var为变量 val name:Type = ***,变量名后加冒号 ...
- python系列之 - 并发编程(进程池,线程池,协程)
需要注意一下不能无限的开进程,不能无限的开线程最常用的就是开进程池,开线程池.其中回调函数非常重要回调函数其实可以作为一种编程思想,谁好了谁就去掉 只要你用并发,就会有锁的问题,但是你不能一直去自己加 ...
- Generator和Coroutine学习
简单的生产者消费者模型 #!/usr/bin/python2.7 def consumer(): while True: newn = yield print 'Consumer : {}'.form ...
- python并发编程之进程池,线程池,协程
需要注意一下不能无限的开进程,不能无限的开线程最常用的就是开进程池,开线程池.其中回调函数非常重要回调函数其实可以作为一种编程思想,谁好了谁就去掉 只要你用并发,就会有锁的问题,但是你不能一直去自己加 ...
- Scala详解
1 快速入门... 4 1.1 分号... 4 1.2 常变量声明... 4 1.2.1 val常量... 4 1.2.2 ...
随机推荐
- spring3: helloword
借助:eclipse,mavn,spring-tool-sitedchapter2.helloworld 项目搭建好了,让我们来开发接口,此处我们只需实现打印“Hello World!”,所以我们定义 ...
- 使用科大讯飞时碰上的问题(unity调用Android)
使用科大讯飞的时候公司已经有人配置好了Android项目,由于装机量的限制,所以基本上要更换里面的资源和更改app_id,然而在unity那边调用的时候总是出现各种各样的问题,特此记录下来 1.唤醒未 ...
- lucas定理学习
Lucas定理是用来求 c(n,m) mod p,p为素数的值. 表达式: C(n,m)%p=C(n/p,m/p)*C(n%p,m%p)%p 当我们遇到求一个N,M很大的组合数的时候,递推法就显得很耗 ...
- R-一页多图
https://blog.csdn.net/ailsa__/article/details/45932753
- Unity在协程(Coroutines)内开启线程(Threading )
孙广东 2017.6.13 http://blog.csdn.NET/u010019717 为什么要在协程中开启线程, 因为很多时候我们是需要线程执行完成后回到主线程的.然后主线程在继续执行后续的操 ...
- c++ 基础知识 0001 const 知识1
1. C++ const用法 尽可能使用const 2. C++ const 允许指定一个语义约束,编译器会强制实施这个约束,允许程序员告诉编译器某值是保持不变的.如果在编程中确实有某个值保持不变,就 ...
- fedora 安装新字体 courier new xxx
fedora安装新字体 1.将windows字体拷贝到/usr/share/fonts/truetype下面,文件夹名字可以随便起 cp /media/c/WINDOWS/Fonts/* /usr/s ...
- HDU - 5088: Revenge of Nim II (问是否存在子集的异或为0)
Nim is a mathematical game of strategy in which two players take turns removing objects from distinc ...
- 微软SaaS多租户解决方案
微软SaaS多租户解决方案 docs.microsoft.com/en-us/azure/sql-database/saas-tenancy-app-design-patterns https://d ...
- python3 tesserocr 安装 来解决部分爬虫遇到的字符识别问题
1. OCR OCR,即Optical Character Recognition,光学字符识别,是指通过扫描字符,然后通过其形状将其翻译成电子文本的过程.对于图形验证码来说,它们都是一些不规则的字符 ...