[python]生成器yield from
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了[python]生成器yield from,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含5607字,纯文字阅读大概需要9分钟。
内容图文
![[python]生成器yield from](/upload/InfoBanner/zyjiaocheng/855/1239651acb2f42f0af28744ef32a5ece.jpg)
#python3.3新加了yield from语法
from itertools import chain
#chain,把几个可迭代的对象,连接在一起,进行迭代遍历
my_list = [1,2,3]
my_dict = {
"bobby1":"http://projectsedu.com",
"bobby2":"http://www.imooc.com",
}
for value in chain(my_list, my_dict, range(5,10)):
print(value)
==========================================
1
2
3
bobby1
bobby2
5
6
7
8
9
#####################################################
#实现的原理
def my_chain(*args, **kwargs):
for my_iterable in args:
for value in my_iterable:
yield value
#yield from iterable
def my_chain(*args, **kwargs):
for my_iterable in args:
yield from my_iterable #yield from 后面跟一个可迭代对象,可把代码更加简洁。结果也是一样的
for value in my_chain(my_list, my_dict, range(5,10)):
print(value) #打印出来的结果也是一样的。
#yield和yield from的区别
def g1(iterable):
yield iterable
def g2(iterable):
yield from iterable
for value in g1(range(10)):
print(value) #range(0, 10) 生成的原来的值
for value in g2(range(10)):
print(value) #yield from会迭代range(0, 10)里面的每一个值
=========================================
range(0, 10)
0
1
2
3
4
5
6
7
8
9
# yield from应用
def g1(gen):
yield from gen
def main():
g = g1()
g.send(None)
#1. main 调用方 g1(委托生成器) gen 子生成器
#1. yield from会在调用方与子生成器之间建立一个双向通道
# 调用方,发送的close、send、throw都是直接发送到 子生成器里面的
# yield from的一个使用例子
final_result = {}
def sales_sum(pro_name):
total = 0
nums = []
while True:
x = yield #4.这里接受处理值
print(pro_name+"销量: ", x)
if not x: #6.x是none时,就会退出
break
total += x
nums.append(x)
return total, nums #7.返回这个值
def middle(key):
while True:
final_result[key] = yield from sales_sum(key) #2.激活了yield from 8.StopIteration时,return值返回给final_result
print(key+"销量统计完成!!.")
# 注意的点
# 调用方main是直接和子生成器sales_sum通信的
def main():
data_sets = {
"bobby牌面膜": [1200, 1500, 3000],
"bobby牌手机": [28,55,98,108 ],
"bobby牌大衣": [280,560,778,70],
}
for key, data_set in data_sets.items():
print("start key:", key)
m = middle(key)
m.send(None) # 1.预激middle协程 也可以使用next
for value in data_set:
m.send(value) # 3.给协程传递每一组的值[1200, 1500, 3000]
m.send(None) #5.send none时结束
print("final_result:", final_result)
if __name__ == '__main__':
main()
====================================================================================
output
start key: bobby牌面膜
bobby牌面膜销量: 1200
bobby牌面膜销量: 1500
bobby牌面膜销量: 3000
bobby牌面膜销量: None
bobby牌面膜销量统计完成!!.
start key: bobby牌手机
bobby牌手机销量: 28
bobby牌手机销量: 55
bobby牌手机销量: 98
bobby牌手机销量: 108
bobby牌手机销量: None
bobby牌手机销量统计完成!!.
start key: bobby牌大衣
bobby牌大衣销量: 280
bobby牌大衣销量: 560
bobby牌大衣销量: 778
bobby牌大衣销量: 70
bobby牌大衣销量: None
bobby牌大衣销量统计完成!!.
final_result: {'bobby牌面膜': (5700, [1200, 1500, 3000]), 'bobby牌手机': (289, [28, 55, 98, 108]), 'bobby牌大衣': (1688, [280, 560, 778, 70])}
#上面的例子为什么要使用 yield from
def g():
x = yield 'ooo'
print(x)
my_g = g()
my_g.send(None)
my_g.send('ffffff')
=========================================================
ffffff
Traceback (most recent call last):
File "C:/DLLM/aas.py", line 6, in <module>
my_g.send('ffffff')
StopIteration
#结束这个生成器时,会有一个StopIteration异常
----------------------------------------------------------------------
def sales_sum(pro_name):
total = 0
nums = []
while True:
x = yield
print(pro_name+"销量: ", x)
if not x:
break
total += x
nums.append(x)
return total, nums
if __name__ == "__main__":
my_gen = sales_sum("bobby牌手机")
my_gen.send(None)
my_gen.send(1200)
my_gen.send(1500)
my_gen.send(3000)
my_gen.send(None)
=============================================================================
StopIteration Traceback (most recent call last)
<ipython-input-21-d7e46ea3332d> in <module>()
17 my_gen.send(1500)
18 my_gen.send(3000)
---> 19 my_gen.send(None)
20
StopIteration: (5700, [1200, 1500, 3000])
#结束这个生成器时,会有一个StopIteration异常
#如果我们自己处理要这样
if __name__ == "__main__":
my_gen = sales_sum("bobby牌手机")
my_gen.send(None)
my_gen.send(1200)
my_gen.send(1500)
my_gen.send(3000)
try:
my_gen.send(None)
except StopIteration as e:
result = e.value
print(result)
===================================
bobby牌手机销量: 1200
bobby牌手机销量: 1500
bobby牌手机销量: 3000
bobby牌手机销量: None
(5700, [1200, 1500, 3000])
#用yield from能使我们省去了catch StopIteration的异常
“”"
- 子生成器可能只是一个迭代器,并不是一个作为协程的生成器,所以它不支持.throw()和.close()方法;
- 如果子生成器支持.throw()和.close()方法,但是在子生成器内部,这两个方法都会抛出异常;
- 调用方让子生成器自己抛出异常
- 当调用方使用next()或者.send(None)时,都要在子生成器上调用next()函数,当调用方使用.send()发送非 None 值时,才调用子生成器的.send()方法;
“”"
“”"
- 子生成器生产的值,都是直接传给调用方的;调用方通过.send()发送的值都是直接传递给子生成器的;如果发送的是 None,会调用子生成器的__next__()方法,如果不是 None,会调用子生成器的.send()方法;
- 子生成器退出的时候,最后的return EXPR,会触发一个StopIteration(EXPR)异常;
- yield from表达式的值,是子生成器终止时,传递给StopIteration异常的第一个参数;
- 如果调用的时候出现StopIteration异常,委托生成器会恢复运行,同时其他的异常会向上 “冒泡”;
- 传入委托生成器的异常里,除了GeneratorExit之外,其他的所有异常全部传递给子生成器的.throw()方法;如果调用.throw()的时候出现了StopIteration异常,那么就恢复委托生成器的运行,其他的异常全部向上 “冒泡”;
- 如果在委托生成器上调用.close()或传入GeneratorExit异常,会调用子生成器的.close()方法,没有的话就不调用。如果在调用.close()的时候抛出了异常,那么就向上 “冒泡”,否则的话委托生成器会抛出GeneratorExit异常。
“”"
内容总结
以上是互联网集市为您收集整理的[python]生成器yield from全部内容,希望文章能够帮你解决[python]生成器yield from所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。