生成器进阶
一、send
1.yield使用的限制
def generator(): print(123) yield 1 print(234) yield 2 print(345) g=generator() ret=g.__next__() print(ret) ret=g.__next__() print(ret) # ret=g.__next__() #触发从上一个yield开始,但是再没有返回值了,所以会打印345,之后会报错。 # print(ret) #123 #1 #234 #2
2.引入send
print("*"*40)
def generator2():
print(123)
num=yield 1 #在此处停住,然后传进来的值,就会在这里传入,所以num="打印~"
print("="*5,num)
print(234)
yield 2
g2=generator2()
ret=g2.__next__()
print(ret)
ret=g2.send("打印~") #send效果和next基本一样,都可以获取下一个值,但同时会传入一个值进去给上一个yield值的位置
print(ret)
#使用send的注意事项:
#1.第一次使用生成器必须使用next获取下一个值
#2.最后一个yield不能接收外部的值
#3.yield接收值之后,后面必须还有一个yield,哪怕最后的yield不返回任何值
二、需求:求移动平均值(avg=sum/count)
1.使用生成器
def averagex(): sum = 0 count = 0 avg = 0 while True: num = yield avg #第一次执行时,不关心avg是多少 sum += num count += 1 avg = sum / count avgx = averagex() avgx.__next__() while True: sendnum=int(input("请输入要加入的值(输入0结束):")) if sendnum==0: break avgc = avgx.send(sendnum) # 此时只能计算一个平均值 print("avgx=",avgc) # 请输入要加入的值(输入0结束):2 # avgx= 2.0 # 请输入要加入的值(输入0结束):4 # avgx= 3.0 # 请输入要加入的值(输入0结束):6 # avgx= 4.0 # 请输入要加入的值(输入0结束):9 # avgx= 5.25 # 请输入要加入的值(输入0结束):
2.使用生成器和装饰器
def initx(func): def inner(*args,**kwargs): f=func(*args,**kwargs) f.__next__() return f return inner #这一步非常重要 @initx #->avwragex=initx(average) def averagex(): sum = 0 count = 0 avg = 0 while True: num = yield avg #第一次执行时,不关心avg是多少 sum += num count += 1 avg = sum / count avgx = averagex() #->inner # avgx.__next__() #使用时少写next while True: sendnum=int(input("请输入要加入的值(输入0结束):")) if sendnum==0: break avgc = avgx.send(sendnum) # 此时只能计算一个平均值 print("avgx=",avgc) # 请输入要加入的值(输入0结束):2 # avgx= 2.0 # 请输入要加入的值(输入0结束):4 # avgx= 3.0 # 请输入要加入的值(输入0结束):6 # avgx= 4.0 # 请输入要加入的值(输入0结束):9 # avgx= 5.25 # 请输入要加入的值(输入0结束):
四、yield from
flag1=1 def generator(): a='abcd' b='1234' #一个一个返回(一次返回几个,分批返回) for i in a: yield i for i in b: yield i g=generator() for i in g: print(i,end="") flag2=2 print("*"*40) def generator2(): a="abcdef" b="123456" yield from a yield from b g2=generator2() for i in g2: print(i,end="")