生成器(generator)
1.生成器簡(jiǎn)介
首先請(qǐng)確信,生成器就是一種迭代器。生成器擁有next方法并且行為與迭代器完全相同,這意味著生成器也可以用于Python的for循環(huán)中。另外,對(duì)于生成器的特殊語法支持使得編寫一個(gè)生成器比自定義一個(gè)常規(guī)的迭代器要簡(jiǎn)單不少,所以生成器也是最常用到的特性之一。
從Python2.5開始,[PEP342:通過增強(qiáng)生成器實(shí)現(xiàn)協(xié)同程序]的實(shí)現(xiàn)為生成器加入了更多的特性,這意味著生成器還可以完成更多的工作。這部分我們會(huì)在稍后的部分介紹。
2.生成器函數(shù)
2.1.使用生成器函數(shù)定義生成器
如何獲取一個(gè)生成器?首先來看一小段代碼:
>>>defget_0_1_2():
...yield0
...yield1
...yield2
...
>>>get_0_1_2
我們定義了一個(gè)函數(shù)get_0_1_2,并且可以查看到這確實(shí)是函數(shù)類型。但與一般的函數(shù)不同的是,get_0_1_2的函數(shù)體內(nèi)使用了關(guān)鍵字yield,這使得get_0_1_2成為了一個(gè)生成器函數(shù)。生成器函數(shù)的特性如下:
調(diào)用生成器函數(shù)將返回一個(gè)生成器;
>>>generator=get_0_1_2()
>>>generator
第一次調(diào)用生成器的next方法時(shí),生成器才開始執(zhí)行生成器函數(shù)(而不是構(gòu)建生成器時(shí)),直到遇到y(tǒng)ield時(shí)暫停執(zhí)行(掛起),并且yield的參數(shù)將作為此次next方法的返回值;
>>>generator.next()
之后每次調(diào)用生成器的next方法,生成器將從上次暫停執(zhí)行的位置恢復(fù)執(zhí)行生成器函數(shù),直到再次遇到y(tǒng)ield時(shí)暫停,并且同樣的,yield的參數(shù)將作為next方法的返回值;
>>>generator.next()
>>>generator.next()
如果當(dāng)調(diào)用next方法時(shí)生成器函數(shù)結(jié)束(遇到空的return語句或是到達(dá)函數(shù)體末尾),則這次next方法的調(diào)用將拋出StopIteration異常(即for循環(huán)的終止條件);
>>>generator.next()
Traceback(mostrecentcalllast):
File"",line1,in
StopIteration
生成器函數(shù)在每次暫停執(zhí)行時(shí),函數(shù)體內(nèi)的所有變量都將被封存(freeze)在生成器中,并將在恢復(fù)執(zhí)行時(shí)還原,并且類似于閉包,即使是同一個(gè)生成器函數(shù)返回的生成器,封存的變量也是互相獨(dú)立的。
我們的小例子中并沒有用到變量,所以這里另外定義一個(gè)生成器來展示這個(gè)特點(diǎn):
>>>deffibonacci():
...a=b=1
...yielda
...yieldb
...whileTrue:
...a,b=b,a+b
...yieldb
...
>>>fornuminfibonacci():
...ifnum>100:break
...printnum,
...
1123581321345589
看到whileTrue可別太吃驚,因?yàn)樯善骺梢話炱?,所以是延遲計(jì)算的,無限循環(huán)并沒有關(guān)系。這個(gè)例子中我們定義了一個(gè)生成器用于獲取斐波那契數(shù)列。
以上內(nèi)容為大家介紹了Python函數(shù)式編程指南之生成器,希望對(duì)大家有所幫助,如果想要了解更多Python相關(guān)知識(shí),請(qǐng)關(guān)注IT培訓(xùn)機(jī)構(gòu):千鋒教育。