码迷,mamicode.com
首页 > 编程语言 > 详细

python生成器——懒到欠揍,但很经济

时间:2018-07-15 23:13:39      阅读:221      评论:0      收藏:0      [点我收藏+]

标签:range   类型   word   可迭代对象   种类   dict   def   end   个数   

生成器的特点是工作到一半,就会停下来看别人干活直至有人踢它屁股,这时它才继续往下干活。实现这一功能的精髓要用到yield。

生成器是一种特殊的迭代器,因此我们先来了解一下什么是迭代器。我们都知道著名的斐波那契数列:1、1、2、3、5、8、13、21、34……从第三个数开始,每个数都可以由其前面的两个数相加得到,这就是一个迭代过程。很显然,这是一个不收敛的数列,我们无法用列表或者使集合去一次性将它们提取出来。这时候,如果我们把这样一个迭代过程封装成一个迭代器,只有在调用一次它的时候它才进行一次迭代,并且只保留当前的迭代结果,这样一来,程序的运行速度能得到提高,同时也不会对内存造成严重的负担。迭代器可以表示一个无限大的数据流,也可以表示一个有限的数据流。

从代码的角度讲,所有可以被next()函数调用并不断返回下一个值的对象就叫做迭代器:Iterator。与迭代器相近的一个概念是可迭代对象(Iterable),凡是可用for循环遍历的对象都是可迭代对象,比如list、dict和str等。但是这几个对象不是迭代器,这一点在上一段已经从迭代器的特点说明,不再赘述。然而,世事无绝对,通过iter()函数,可以将它们变成迭代器。

由此,我们可以建立这样一个斐波那契数列生成器:

 1 def generate():
 2     a,b,c = 0,0,1
 3     while a < 20:  #a用来计数
 4 
 5         b,c = c,b +c  #迭代公式
 6         a = a + 1
 7         yield c
 8     return "fault"  #出错时的返回值
 9 
10 
11 y = generate()   #产生一个生成器对象,但不调用生成器
12 for i in range(13):  #调用13次
13     print(y.__next__())  #使用next()方法调用生成器

yield的作用是让生成器在这里暂停执行,执行下一条程序指令。当下一次调用next()函数时,生成器从暂停的地方继续往下执行。一次,每调用一次产生一个值,调用13次产生13个值,如下图所示

技术分享图片

这种类型的生成器并不需要参数,当我们需要给生成器内部传递参数时,我们需要用到send()函数,因为next()函数不具备该功能。看下面这样一段代码:

 1 def sing(word1):
 2     print(word1)
 3     while True:
 4         word2 = yield  #每次调用时生成器都停留在这里
 5         print(word2)
 6 
 7 
 8 a = sing("如今走过这世间")
 9 a.send(None)  #可以替换成a.__next__()
10 a.send("万般流连")

上述代码,如果不用while循环,则没办法使每次调用的结果程序都停留在yield这里,而是执行完print(word2)变结束了,这使程序会报错。在第一次使用需要传递参数的生成器时,我们不能直接使用send()函数传递我们想传递的参数,因为此时函数停在yeild,并不需要到这个参数。因此我们可以用next()函数来进行第一次调用,然后再调用send()传递参数并调用。当然,如果我们非要用send()函数实现第一次调用时,应该传递一个空参数。运行结果如下所示:

技术分享图片

至此,大功告成!

python生成器——懒到欠揍,但很经济

标签:range   类型   word   可迭代对象   种类   dict   def   end   个数   

原文地址:https://www.cnblogs.com/cxy-learning/p/cxy-learn.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!