欢迎来到天天文库
浏览记录
ID:17480785
大小:23.14 KB
页数:9页
时间:2018-09-02
《python函数式编程指南生成器》由会员上传分享,免费在线阅读,更多相关内容在教育资源-天天文库。
1、Python函数式编程指南(四):生成器生成器是迭代器,同时也并不仅仅是迭代器,不过迭代器之外的用途实在是不多,所以我们可以大声地说:生成器提供了非常方便的自定义迭代器的途径。这是函数式编程指南的最后一篇,似乎拖了一个星期才写好,嗯……转载请注明原作者和原文地址:)4.生成器(generator)4.1.生成器简介首先请确信,生成器就是一种迭代器。生成器拥有next方法并且行为与迭代器完全相同,这意味着生成器也可以用于Python的for循环中。另外,对于生成器的特殊语法支持使得编写一个生成器比自定义
2、一个常规的迭代器要简单不少,所以生成器也是最常用到的特性之一。从Python2.5开始,[PEP342:通过增强生成器实现协同程序]的实现为生成器加入了更多的特性,这意味着生成器还可以完成更多的工作。这部分我们会在稍后的部分介绍。4.2.生成器函数4.2.1.使用生成器函数定义生成器如何获取一个生成器?首先来看一小段代码:123>>>def get_0_1_2():... yield 0... yield 14567... yield 2...>>>get_0_1_23、_1_2at0x00B2CB70>我们定义了一个函数get_0_1_2,并且可以查看到这确实是函数类型。但与一般的函数不同的是,get_0_1_2的函数体内使用了关键字yield,这使得get_0_1_2成为了一个生成器函数。生成器函数的特性如下:1.调用生成器函数将返回一个生成器;123>>>generator= get_0_1_2()>>>generator2.第一次调用生成器的next方法时,生成器才开始执行生成器函数4、(而不是构建生成器时),直到遇到yield时暂停执行(挂起),并且yield的参数将作为此次next方法的返回值;12>>>generator.next()03.之后每次调用生成器的next方法,生成器将从上次暂停执行的位置恢复执行生成器函数,直到再次遇到yield时暂停,并且同样的,yield的参数将作为next方法的返回值;1234>>>generator.next()1>>>generator.next()24.如果当调用next方法时生成器函数结束(遇到空的return语句或是到达函数体末尾)5、,则这次next方法的调用将抛出StopIteration异常(即for循环的终止条件);1234>>>generator.next()Traceback(mostrecentcalllast): File "",line1,in StopIteration1.生成器函数在每次暂停执行时,函数体内的所有变量都将被封存(freeze)在生成器中,并将在恢复执行时还原,并且类似于闭包,即使是同一个生成器函数返回的生成器,封存的变量也是互相独立的。 我们的小例子中并没有用到变6、量,所以这里另外定义一个生成器来展示这个特点:12345678910111213>>>def fibonacci():... a= b= 1... yield a... yield b... while True:... a,b= b,a+b... yield b...>>>for numin fibonacci():... if num>100:break... print num,...1 1 2 3 5 8 13 21 34 55 892.看到whileTrue可别太吃惊7、,因为生成器可以挂起,所以是延迟计算的,无限循环并没有关系。这个例子中我们定义了一个生成器用于获取斐波那契数列。4.2.2.生成器函数的FAQ接下来我们来讨论一些关于生成器的有意思的话题。1.你的例子里生成器函数都没有参数,那么生成器函数可以带参数吗? 当然可以啊亲,而且它支持函数的所有参数形式。要知道生成器函数也是函数的一种:)12345>>>def counter(start=0):... while True:... yield start... start+= 1...1.这是一8、个从指定数开始的计数器。2.既然生成器函数也是函数,那么它可以使用return输出返回值吗? 不行的亲,是这样的,生成器函数已经有默认的返回值——生成器了,你不能再另外给一个返回值;对,即使是returnNone也不行。但是它可以使用空的return语句结束。如果你坚持要为它指定返回值,那么Python将在定义的位置赠送一个语法错误异常,就像这样:123456>>>def i_wanna_return():... yield None... retu
3、_1_2at0x00B2CB70>我们定义了一个函数get_0_1_2,并且可以查看到这确实是函数类型。但与一般的函数不同的是,get_0_1_2的函数体内使用了关键字yield,这使得get_0_1_2成为了一个生成器函数。生成器函数的特性如下:1.调用生成器函数将返回一个生成器;123>>>generator= get_0_1_2()>>>generator2.第一次调用生成器的next方法时,生成器才开始执行生成器函数
4、(而不是构建生成器时),直到遇到yield时暂停执行(挂起),并且yield的参数将作为此次next方法的返回值;12>>>generator.next()03.之后每次调用生成器的next方法,生成器将从上次暂停执行的位置恢复执行生成器函数,直到再次遇到yield时暂停,并且同样的,yield的参数将作为next方法的返回值;1234>>>generator.next()1>>>generator.next()24.如果当调用next方法时生成器函数结束(遇到空的return语句或是到达函数体末尾)
5、,则这次next方法的调用将抛出StopIteration异常(即for循环的终止条件);1234>>>generator.next()Traceback(mostrecentcalllast): File "",line1,in StopIteration1.生成器函数在每次暂停执行时,函数体内的所有变量都将被封存(freeze)在生成器中,并将在恢复执行时还原,并且类似于闭包,即使是同一个生成器函数返回的生成器,封存的变量也是互相独立的。 我们的小例子中并没有用到变
6、量,所以这里另外定义一个生成器来展示这个特点:12345678910111213>>>def fibonacci():... a= b= 1... yield a... yield b... while True:... a,b= b,a+b... yield b...>>>for numin fibonacci():... if num>100:break... print num,...1 1 2 3 5 8 13 21 34 55 892.看到whileTrue可别太吃惊
7、,因为生成器可以挂起,所以是延迟计算的,无限循环并没有关系。这个例子中我们定义了一个生成器用于获取斐波那契数列。4.2.2.生成器函数的FAQ接下来我们来讨论一些关于生成器的有意思的话题。1.你的例子里生成器函数都没有参数,那么生成器函数可以带参数吗? 当然可以啊亲,而且它支持函数的所有参数形式。要知道生成器函数也是函数的一种:)12345>>>def counter(start=0):... while True:... yield start... start+= 1...1.这是一
8、个从指定数开始的计数器。2.既然生成器函数也是函数,那么它可以使用return输出返回值吗? 不行的亲,是这样的,生成器函数已经有默认的返回值——生成器了,你不能再另外给一个返回值;对,即使是returnNone也不行。但是它可以使用空的return语句结束。如果你坚持要为它指定返回值,那么Python将在定义的位置赠送一个语法错误异常,就像这样:123456>>>def i_wanna_return():... yield None... retu
此文档下载收益归作者所有