咱先看看yield和yield form 的区别在哪儿,代码如下,全部传入range(10)
def g1(iterable):
yield iterable
def g2(iterable):
yield from iterable
for value in g1(range(10)):
print(value)
for value in g2(range(10)):
print(value)
结果: yield 输出的是range(10),而yield from 输出了他的迭代数据.
range(0, 10)
0
1
2
3
4
5
6
7
8
9
在学习yield from之前先认识一个库 : chain ,这个库可以迭代任意多个数据,包括list,dict,等等.
from itertools import chain
my_list = [1,2,3]
my_dict = {
"bobby":"http://project.com",
"bobby2":"http://www.immoc.com"
}
for value in chain(my_dict,my_list,range(5,10)):
print(value)
它实现的功能是这样的,把其中的数据都一个个的迭代出来
bobby
bobby2
1
2
3
5
6
7
8
9
现在我们自己实现一个chain
# 自定义一个chain
def my_chain(*args,**kwargs):
for my_iterable in args:
for value in my_iterable:
yield value
for value in my_chain(my_dict,my_list,range(5,10)):
print(value)
产生的值也是
bobby
bobby2
1
2
3
5
6
7
8
9
现在呢,用yield from 实现一下
def my_chain(*args,**kwargs):
for my_iterable in args:
yield from my_iterable # yield from可以迭代其中的所有数据
for value in my_chain(my_dict,my_list,range(5,10)):
print(value)
生成的结果如下,yield from 简化了上面的代码,其实yield from 不止做到了迭代所有的数据,它内部实现了很多异常的处理
bobby
bobby2
1
2
3
5
6
7
8
9
而且使用yield from 的使用方法,,他会在调用方和子生成器之间建立一个双向通道,他们实现连接
def g1(gen):
yield from gen
def main():
g = g1()
g.send(None)
# main 调用方 g1(委托生成器),gen子生成器
# yield from 会在调用方和子生成器之间建立一个双向通道
这是一个yield from实战的例子,
final_result = {}
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
def middle(key):
while 1:
final_result[key] = yield from sales_sum(key)
print(key+"销量统计完成!")
def main():
data_set = {
"bobby牌面膜":[1200,1500,3000],
"bobby牌手机":[1600,1700,13000,1200],
"bobby牌大衣":[2300,2100,10,60]
}
for key,data_set in data_set.items():
print("start key",key)
m = middle(key)
m.send(None) # 预激活middle协程
for value in data_set:
m.send(value) # 给协程传递每一组的值
m.send(None)
print("final_result",final_result)
"""
# 详细剖析
"""
def sales_sum1(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_sum1("boobby牌手机")
my_gen.send(None)
my_gen.send(1000)
my_gen.send(1300)
my_gen.send(1200)
try:
my_gen.send(None)# 会异常,把返回值显示出来
except StopIteration as e:# 需要处理异常
result = e.value
print(result) # yield from会实现这些功能处理异常并返回值
它最终实现的效果是这样的,大家可以拷贝上面的代码,到IED中自己分析运行一下.这就涉及到了上面的上面yield from的使用方法.涉及到了调用方,委托生成器和子生成器,并且子生成器会和调用方实现一个双向通道.
boobby牌手机销量: 1000
boobby牌手机销量: 1300
boobby牌手机销量: 1200
boobby牌手机销量: None
(3500, [1000, 1300, 1200])