生成器进阶

一、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="")

 

posted @ 2019-06-09 17:01  玉石非玉  阅读(135)  评论(0编辑  收藏  举报