def gen(): """子生成器""" yield 1 def gen1(gen): """委托生成器""" yield from gen def main(): """调用方""" g = gen() g1 = gen1(g) g1.send(None) # 启动生成器
上面的代码有3个角色, main是调用方. gen1:委托生成器, gen:子生成器
yield from会在调用方与子生成器之间建立一个双方通道, 这样,调用方和子生成器之间就可以进行通信(send, close , throw )
示例
final_result = {} def sales_num(key): total = 0 nums = [] while True: x = yield # 使用while循环不断的从调用方接收值 print(key + '销量:', x) if not x: break # 结束while循环 total += x nums.append(x) return total, nums # 生成器的值返回到delegate委托生成器中 def delegate(key): """委托生成器""" while True: final_result[key] = yield from sales_num(key) print(key + '销量统计完成') def main(): data_set = { "欧莱雅": [100, 200, 400], "法泉": [12, 4354, 67], "死贵人": [212, 23423, 545] } for key, data in data_set.items(): print('start key:', key) d = delegate(key) d.send(None) for value in data: d.send(value) # 这儿是直接将值send到sales_num子生成器中 d.send(None) # 结果一个key的统计 print('final_result:', final_result) if __name__ == '__main__': main()
打印:
start key: 欧莱雅 欧莱雅销量: 100 欧莱雅销量: 200 欧莱雅销量: 400 欧莱雅销量: None 欧莱雅销量统计完成 start key: 法泉 法泉销量: 12 法泉销量: 4354 法泉销量: 67 法泉销量: None 法泉销量统计完成 start key: 死贵人 死贵人销量: 212 死贵人销量: 23423 死贵人销量: 545 死贵人销量: None 死贵人销量统计完成 final_result: {'欧莱雅': (700, [100, 200, 400]), '法泉': (4433, [12, 4354, 67]), '死贵人': (24180, [212, 23423, 545])}
补充
def sales_num(key): """定义一个生成器""" total = 0 nums = [] while True: x = yield print(key + '销量:', x) if not x: break # 结束while循环 total += x nums.append(x) return total, nums if __name__ == '__main__': g = sales_num("苹果手机") g.send(None) # 激活生成器, 也可以使用next(g) g.send(5000) # send一个值到生成器内部, 就是x接收的 g.send(1000) # send一个值到生成器内部, 就是x接收的 g.send(5000) # send一个值到生成器内部, 就是x接收的 g.send(None) # 这次send(None) 表过结束生成器,生成器会抛出StopIteration异常,这是个正常的异常,然后返回total, nums
1 2 3 4 5 6 7 8 | Traceback (most recent call last): 苹果手机销量: 5000 File "E:/ws/python/LearnFlask/test/mooic/yield_test.py" , line 21 , in <module> 苹果手机销量: 1000 g.send( None ) 苹果手机销量: 5000 StopIteration: ( 11000 , [ 5000 , 1000 , 5000 ]) 苹果手机销量: None |
为了优雅的结束生成器, 需要try .... StopIteration....
下面是优雅的结束生成器的代码
def sales_num(key): """定义一个生成器""" total = 0 nums = [] while True: x = yield print(key + '销量:', x) if not x: break # 结束while循环 total += x nums.append(x) return total, nums if __name__ == '__main__': g = sales_num("苹果手机") g.send(None) # 激活生成器, 也可以使用next(g) g.send(5000) # send一个值到生成器内部, 就是x接收的 g.send(1000) # send一个值到生成器内部, 就是x接收的 g.send(5000) # send一个值到生成器内部, 就是x接收的 try: g.send(None) # 这次send(None) 表过结束生成器,生成器会抛出StopIteration异常,这是个正常的异常,然后返回total, nums except StopIteration as e: print(e.value) # (11000, [5000, 1000, 5000]) 通过异常,获取生成器的返回值
苹果手机销量: 5000 苹果手机销量: 1000 苹果手机销量: 5000 苹果手机销量: None (11000, [5000, 1000, 5000])
通过上面的yield from示例可知,yield from帮我们处理了try...stopiteration...异常, 因为我们并没有手动去处理.
日拱一卒无有尽,功不唐捐终入海
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 深入理解 Mybatis 分库分表执行原理
· 如何打造一个高并发系统?
· .NET Core GC压缩(compact_phase)底层原理浅谈
· 现代计算机视觉入门之:什么是图片特征编码
· .NET 9 new features-C#13新的锁类型和语义
· 手把手教你在本地部署DeepSeek R1,搭建web-ui ,建议收藏!
· Spring AI + Ollama 实现 deepseek-r1 的API服务和调用
· 《HelloGitHub》第 106 期
· 数据库服务器 SQL Server 版本升级公告
· C#/.NET/.NET Core技术前沿周刊 | 第 23 期(2025年1.20-1.26)