title: 生成器进阶
top: 43
date: 2022-07-07 15:33:17
tags:
- yield from & yield
- 生成器
categories: - python
- 生成器不仅可以产生值,还可以接收值;
gen.send()
- 生成器是可以关闭的;
gen.close()
- 生成器是可以抛出异常的;
gen.throw()
def gen():
"""
第一个yield 对应的赋值是从第二次调用send中获取;
第二个yield 对应的赋值是从第三次调用send中获取;
---
也即,如果想用send获取n次值,则必须有n+1个yield,否则会报错
"""
name1 = yield "https://bgape002.gitee.io/blog/"
print(name1 + ": https://bgape002.gitee.io/blog/")
name2 = yield 2
print(name2 + ": 2")
yield 3
return name1
if __name__ == "__main__":
"""
第一次send 传递的值必须是None,作为启动;获得第一个yield对应的值
第二次send 传递的值可自定义;活动第二个yield对应的值
"""
gen = gen() # 通过生成器函数构建生成器
# y1 = next(gen)
y1 = gen.send(None) # 在调用send传递非None值前,必须先启动依次生成器,方式有两种1). gen.send(None); 2). next(gen)
y2 = gen.send("bgape")
gen.send("shshg") # 这行代码是有返回值的,返回值为3.
print(f"y1: {y1}, y2: {y2}")
"""output
bgape: https://bgape002.gitee.io/blog/
shshg: 2
y1: https://bgape002.gitee.io/blog/, y2: 2
"""
"""python3.3以上版本才会支持yield from
1). yield from 会在调用方与子生成器之间建立一个双向通道
"""
final_resulit = {}
# 子生成器
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 True:
final_resulit[key] = yield from sales_sum(key) # = 左侧获取值为sales_sum的返回值
print(key + "销量统计完成!!")
# 调用方
def main():
data_sets = {
"bgape手机": [2200, 3300, 5500],
"bgape手机壳": [22, 33, 55],
"bgape充电器": [220, 330, 550],
}
for key, data_set in data_sets.items():
print("start key: ", key)
m = middle(key)
m.send(None) # 预激middle协程
for val in data_set:
m.send(val) # 给协程传递值
m.send(None) # 生成器调用结束标志
print("final result: ", final_resulit)
if __name__ == "__main__":
main()
"""output
start key: bgape手机
bgape手机销量: 2200
bgape手机销量: 3300
bgape手机销量: 5500
bgape手机销量: None
bgape手机销量统计完成!!
start key: bgape手机壳
bgape手机壳销量: 22
bgape手机壳销量: 33
bgape手机壳销量: 55
bgape手机壳销量: None
bgape手机壳销量统计完成!!
start key: bgape充电器
bgape充电器销量: 220
bgape充电器销量: 330
bgape充电器销量: 550
bgape充电器销量: None
bgape充电器销量统计完成!!
final result: {'bgape手机': (11000, [2200, 3300, 5500]), 'bgape手机壳': (110, [22, 33, 55]), 'bgape充电器': (1100, [220, 330, 550])}
"""
"""yield + yield from + 递归
"""
def func(n):
result = n ** 2
yield result
if n < 100:
yield from func(result)
for x in func(2):
print(x)
"""output
4
16
256
65536
"""