python生成器——懒到欠揍,但很经济
Posted cxy-learning
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python生成器——懒到欠揍,但很经济相关的知识,希望对你有一定的参考价值。
生成器的特点是工作到一半,就会停下来看别人干活直至有人踢它屁股,这时它才继续往下干活。实现这一功能的精髓要用到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生成器——懒到欠揍,但很经济的主要内容,如果未能解决你的问题,请参考以下文章