生成器总结

生成器:

  • 语法上和函数类似:生成器和常规函数一样都是使用def定义,差别在于,生成器使用yield返回一个值,这个值本质上是这个生成器的地址,可以供外界使用执行(正所谓授人与鱼,不如授人与渔),yield关键字除了能向外界返回值外,还可以保存当前迭代的状态,以便在外界进行下一轮迭代,而常规函数使用return返回一个值,并结束该函数。
  • 自动实现迭代器协议:所以生成器本质上是一个特殊的迭代器(或者使用了迭代器,如for循环,和sum()函数),由于实现了迭代器协议,所以毫无疑问我们我们可以调用生成器的__next__()方法,以便于获得下一轮迭代,并且如果该生成器没有返回值时,自动残生stopIteration()异常。
  • 状态挂起:生成器的yield语句每返回一个值就会挂起该函数的迭代状态,保留足够的信息,以便之后从离开的地方继续执行。

优点:

  • 生成器可以延迟计算,一次返回一个结果。也就是说,他不会一次生成所有的结果,而生成一个在停止然后继续接受外面的指令可以接着上面的迭代状态继续执行。
def xiadan2():
    for i in range(100):
    yield '鸡蛋%s'%i
print ("去除鸡蛋",xiadan2().__next__())
View Code
  • 生成器有效提高代码的可读性

注意事项:

生成器只能遍历一次,当生成了StopIteration()时候迭代已经结束。

生成器的启动方式:

  • 使用可迭代对象内置的__next__()方法或者next()方法。
  • 使用send()方法:
  • (for i in Test)注:Test为生成器函数
#定义了一个启动器
def test():
    for i in range(4):
        yield i
t=test()
t1=(i for i in t)#仅仅是启动了生成器,并没有调用__next__()
t2=(i for i in t1)#此时t1中并没有值
print(list(t1))#此时才调用了__next__()方法
print(list(t2))#因此,这个列表为空  

 上面程序的运行结果

 

 

  

  仅仅使用send(None)可以启动生成器,其作用相当于调用__next__()方法,然而,send(“发送给yield的参数”)方法将“str”发送给yield关键字,在这里yield关键字有两个作用,第一相当于return,第二是接收send()发送过来的值,所以可以有如下语法:res=yield,将yield接受到的值赋值给res变量。

#定义了一个生成器
def test():
    print('开始啦')
    ret=yield 1   #ret用于接收有send("str")发送过来的值
    print("第一个",ret)
    yield 2
    print("第二个")
    yield 3
t=test()#获取上面所定义的生成器,此时并没有执行
# res=t.__next__()#调用__next__()方法可以启动启动生成器
res=t.send(None)#res接受的是生成器通过yield返回的值
print(res)#此时的res值为1,是通过yield返回的
res=t.send("我是Send发送过来的值")#从上次停止的状态中继续运行生成器,并把send中的值传递给上次停留的yield

 

运行结果如下:

 

posted on 2019-02-28 20:42  小毅哥哥Bob  阅读(378)  评论(0)    收藏  举报

导航