一,
1.yield from
(1) 调用协程为了得到返回值, 协程必须正常终止
(2) 生成器正常终止会发出 StopIteration 异常, 异常对象的 value 属性保存返回值.
(3)yield from 从内部捕获 StopIteration 异常
我们举个例子
- def gen():
- for c in "AB":
- yield c
- #list 直接用生成器作为参数
- print(list(gen()))
- def gen_new():
- yield from "AB"
- print(list(gen_new())
解释: 我们从中可以看出, 两个函数最后返回的结果是一致的, 可以用下面的图片来解释它们的运行过程, 第二个函数增加了一个管道层, 使得这个函数更加灵活; 第一个函数中, list 向迭代器逐一要值, 然后一起输出出来; 第二个函数, 向管道要值, 然后管道收集到所有的迭代数, 然后再一并返回给 list 函数
2. 委派生成器
(1) 包含 yield from 表达式的生成器函数
(2) 委派生成器在 yield from 表达式暂停, 调用方可以直接把数据发给自生成器
(3) 子生成器再把产出的值发给调用方
(4) 子生成器在最后, 解释器会抛出 StopIteration, 并且把返回值附加到异常对象上
举个例子:
- from collections import namedtuple
- ResClass = namedtuple("Res","count average")
- # 子生成器
- def average():
- total = 0.0
- count = 0
- average = None
- ?
- while True:
- term = yield
- #None 是哨兵值
- if term is None:
- break
- total += term
- count += 1
- average = total/count
- ?
- return ResClass(count,average)
- ?
- # 委派生成器
- def grouper(storages,key):
- while True:
- #获取 averager() 返回的值
- storages[key] = yield from average()
- ?
- # 客户端代码
- def abc():
- process_data = {
- "boys_2":[39.0,40.8,43.2,43.1,38.6,41.4,40.6,36.3],
- "boys_1":[1.38,1.5,1.32,1.25,1.37,1.48,1.25,1.49,1.46]
- }
- storages = {}
- for k,v in process_data.items():
- #获取协程
- coroutine = grouper(storages,k)
- #预激协程
- next(coroutine)
- ?
- #发送数据到协程
- for dt in v:
- coroutine.send(dt)
- ?
- #终止协程
- coroutine.send(None)
- print(storages)
- #run
- if __name__ == "__main__":
- abc()
- # 解释:
- #1. 外层 for 循环每次迭代会新建一个 grouper 实例, 赋值给 coroutine 变量; grouper 是委派生成器生成
- #2. 调用 next(coroutine), 预激委派生成器 grouper, 此时进入 while True 循环, 调用子生成器 average
- #3. 内层 for 循环调用 coroutine.send(value), 直接把值传给子生成器 average, 同时, 当前的 grouper
- #4. 内层循环结束后, grouper 实例依旧在 yield from 表达式处暂停, 因此, grouper 函数定义体中
- #5.coroutine.send(None) 终止 averager 子生成器, 子生成器抛出 StopIteration 异常并将返回数组
二, 源码
- d27_4_yield_from_and_delegate_generator.py?
- https://github.com/ruigege66/Python_learning/blob/master/d27_4_yield_from_and_delegate_generator.py
- 2.CSDN:https://blog.csdn.net/weixin_44630050(心悦君兮君不知 - 睿)
3. 博客园: https://www.cnblogs.com/ruigege0000/
来源: http://www.bubuko.com/infodetail-3236020.html