版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
1、 HYPERLINK blo/huxi/archive/2011/07/14/2106863.html Python函數(shù)式編程指南(四):生成器生成器是迭代器,同時(shí)也并不僅僅是迭代器,不過迭代器之外的用途實(shí)在是不多,所以我們可以大聲地說:生成器提供了非常方便的自定義迭代器的途徑。這是函數(shù)式編程指南的最后一篇,似乎拖了一個(gè)星期才寫好,嗯轉(zhuǎn)載請注明原作者和原文地址:)4. 生成器(generator)4.1. 生成器簡介首先請確信,生成器就是一種迭代器。生成器擁有next方法并且行為與迭代器完全相同,這意味著生成器也可以用于Python的for循環(huán)中。另外,對于生成器的特殊語法支持使得編寫一個(gè)生成
2、器比自定義一個(gè)常規(guī)的迭代器要簡單不少,所以生成器也是最常用到的特性之一。從Python 2.5開始,PEP 342:通過增強(qiáng)生成器實(shí)現(xiàn)協(xié)同程序的實(shí)現(xiàn)為生成器加入了更多的特性,這意味著生成器還可以完成更多的工作。這部分我們會(huì)在稍后的部分介紹。4.2. 生成器函數(shù)4.2.1. 使用生成器函數(shù)定義生成器如何獲取一個(gè)生成器?首先來看一小段代碼:1234567 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,
3、這使得get_0_1_2成為了一個(gè)生成器函數(shù)。生成器函數(shù)的特性如下:調(diào)用生成器函數(shù)將返回一個(gè)生成器;123 generator =get_0_1_2() generator第一次調(diào)用生成器的next方法時(shí),生成器才開始執(zhí)行生成器函數(shù)(而不是構(gòu)建生成器時(shí)),直到遇到y(tǒng)ield時(shí)暫停執(zhí)行(掛起),并且yield的參數(shù)將作為此次next方法的返回值;12 generator.next()0之后每次調(diào)用生成器的next方法,生成器將從上次暫停執(zhí)行的位置恢復(fù)執(zhí)行生成器函數(shù),直到再次遇到y(tǒng)ield時(shí)暫停,并且同樣的,yield的參數(shù)將作為next方法的返回值;1234 generator.next()1
4、generator.next()2如果當(dāng)調(diào)用next方法時(shí)生成器函數(shù)結(jié)束(遇到空的return語句或是到達(dá)函數(shù)體末尾),則這次next方法的調(diào)用將拋出StopIteration異常(即for循環(huán)的終止條件);1234 generator.next()Traceback (most recent call last):File, line 1, inStopIteration生成器函數(shù)在每次暫停執(zhí)行時(shí),函數(shù)體內(nèi)的所有變量都將被封存(freeze)在生成器中,并將在恢復(fù)執(zhí)行時(shí)還原,并且類似于閉包,即使是同一個(gè)生成器函數(shù)返回的生成器,封存的變量也是互相獨(dú)立的。我們的小例子中并沒有用到變量,所以這里另
5、外定義一個(gè)生成器來展示這個(gè)特點(diǎn):12345678910111213 deffibonacci():. a =b =1. yielda. yieldb. whileTrue:. a, b =b, a+b. yieldb. fornum infibonacci():. ifnum 100: break. printnum,.1123581321345589看到while True可別太吃驚,因?yàn)樯善骺梢話炱穑允茄舆t計(jì)算的,無限循環(huán)并沒有關(guān)系。這個(gè)例子中我們定義了一個(gè)生成器用于獲取斐波那契數(shù)列。4.2.2. 生成器函數(shù)的FAQ接下來我們來討論一些關(guān)于生成器的有意思的話題。你的例子里生成器函數(shù)都
6、沒有參數(shù),那么生成器函數(shù)可以帶參數(shù)嗎?當(dāng)然可以啊親,而且它支持函數(shù)的所有參數(shù)形式。要知道生成器函數(shù)也是函數(shù)的一種:)12345 defcounter(start=0):. whileTrue:. yieldstart. start +=1.這是一個(gè)從指定數(shù)開始的計(jì)數(shù)器。既然生成器函數(shù)也是函數(shù),那么它可以使用return輸出返回值嗎?不行的親,是這樣的,生成器函數(shù)已經(jīng)有默認(rèn)的返回值生成器了,你不能再另外給一個(gè)返回值;對,即使是return None也不行。但是它可以使用空的return語句結(jié)束。如果你堅(jiān)持要為它指定返回值,那么Python將在定義的位置贈(zèng)送一個(gè)語法錯(cuò)誤異常,就像這樣:123456
7、 defi_wanna_return():. yieldNone. returnNone.File, line 3SyntaxError: returnwith argument inside generator好吧,那人家需要確保釋放資源,需要在try.finally中yield,這會(huì)是神馬情況?(我就是想玩你)我在finally中還yield了一次!Python會(huì)在真正離開try.finally時(shí)再執(zhí)行finally中的代碼,而這里遺憾地告訴你,暫停不算哦!所以結(jié)局你也能猜到吧!1234567891011 defplay_u():. try:. yield1. yield2. yield3
8、. finally:. yield0. forval inplay_u(): printval,.1230*這與return的情況不同。return是真正的離開代碼塊,所以會(huì)在return時(shí)立刻執(zhí)行finally子句。*另外,“在帶有finally子句的try塊中yield”定義在PEP 342中,這意味著只有Python 2.5以上版本才支持這個(gè)語法,在Python 2.4以下版本中會(huì)得到語法錯(cuò)誤異常。如果我需要在生成器的迭代過程中接入另一個(gè)生成器的迭代怎么辦?寫成下面這樣好傻好天真。12345 defsub_generator():. yield1. yield2. forval inco
9、unter(10): yieldval.這種情況的語法改進(jìn)已經(jīng)被定義在PEP 380:委托至子生成器的語法中,據(jù)說會(huì)在Python 3.3中實(shí)現(xiàn),屆時(shí)也可能回饋到2.x中。實(shí)現(xiàn)后,就可以這么寫了:12345678 defsub_generator():. yield1. yield2. yieldfromcounter(10)File, line 4yieldfromcounter(10)SyntaxError: invalid syntax看到語法錯(cuò)誤木有?現(xiàn)在我們還是天真一點(diǎn)吧有更多問題?請回復(fù)此文:)4.3. 協(xié)同程序(coroutine)協(xié)同程序(協(xié)程)一般來說是指這樣的函數(shù):彼此間有
10、不同的局部變量、指令指針,但仍共享全局變量;可以方便地掛起、恢復(fù),并且有多個(gè)入口點(diǎn)和出口點(diǎn);多個(gè)協(xié)同程序間表現(xiàn)為協(xié)作運(yùn)行,如A的運(yùn)行過程中需要B的結(jié)果才能繼續(xù)執(zhí)行。協(xié)程的特點(diǎn)決定了同一時(shí)刻只能有一個(gè)協(xié)同程序正在運(yùn)行(忽略多線程的情況)。得益于此,協(xié)程間可以直接傳遞對象而不需要考慮資源鎖、或是直接喚醒其他協(xié)程而不需要主動(dòng)休眠,就像是內(nèi)置了鎖的線程。在符合協(xié)程特點(diǎn)的應(yīng)用場景,使用協(xié)程無疑比使用線程要更方便。從另一方面說,協(xié)程無法并發(fā)其實(shí)也將它的應(yīng)用場景限制在了一個(gè)很狹窄的范圍,這個(gè)特點(diǎn)使得協(xié)程更多的被拿來與常規(guī)函數(shù)進(jìn)行比較,而不是與線程。當(dāng)然,線程比協(xié)程復(fù)雜許多,功能也更強(qiáng)大,所以我建議大家牢牢地
11、掌握線程即可: HYPERLINK blo/huxi/archive/2010/06/26/1765808.html Python線程指南這一節(jié)里我也就不列舉關(guān)于協(xié)程的例子了,以下介紹的方法了解即可。Python 2.5對生成器的增強(qiáng)實(shí)現(xiàn)了協(xié)程的其他特點(diǎn),在這個(gè)版本中,生成器加入了如下方法:send(value):send是除next外另一個(gè)恢復(fù)生成器的方法。Python 2.5中,yield語句變成了yield表達(dá)式,這意味著yield現(xiàn)在可以有一個(gè)值,而這個(gè)值就是在生成器的send方法被調(diào)用從而恢復(fù)執(zhí)行時(shí),調(diào)用send方法的參數(shù)。12345678910 defrepeater():. n
12、=0. whileTrue:. n =(yieldn). r =repeater() r.next()0 r.send(10)10*調(diào)用send傳入非None值前,生成器必須處于掛起狀態(tài),否則將拋出異常。不過,未啟動(dòng)的生成器仍可以使用None作為參數(shù)調(diào)用send。*如果使用next恢復(fù)生成器,yield表達(dá)式的值將是None。close():這個(gè)方法用于關(guān)閉生成器。對關(guān)閉的生成器后再次調(diào)用next或send將拋出StopIteration異常。throw(type, value=None, traceback=None):這個(gè)方法用于在生成器內(nèi)部(生成器的當(dāng)前掛起處,或未啟動(dòng)時(shí)在定義處)拋出一
13、個(gè)異常。*別為沒見到協(xié)程的例子遺憾,協(xié)程最常見的用處其實(shí)就是生成器。4.4. 一個(gè)有趣的庫:pipe這一節(jié)里我要向諸位簡要介紹pipe。pipe并不是Python內(nèi)置的庫,如果你安裝了easy_install,直接可以安裝它,否則你需要自己下載它: HYPERLINK http:/pypi.pytho/pypi/pipe http:/pypi.pytho/pypi/pipe之所以要介紹這個(gè)庫,是因?yàn)樗蛭覀冋故玖艘环N很有新意的使用迭代器和生成器的方式:流。pipe將可迭代的數(shù)據(jù)看成是流,類似于linux,pipe使用|傳遞數(shù)據(jù)流,并且定義了一系列的“流處理”函數(shù)用于接受并處理數(shù)據(jù)流,并最終再次
14、輸出數(shù)據(jù)流或者是將數(shù)據(jù)流歸納得到一個(gè)結(jié)果。我們來看一些例子。第一個(gè),非常簡單的,使用add求和:123 frompipe import* range(5) | add10求偶數(shù)和需要使用到where,作用類似于內(nèi)建函數(shù)filter,過濾出符合條件的元素:12 range(5) | where(lambdax: x %2=0) | add6還記得我們定義的斐波那契數(shù)列生成器嗎?求出數(shù)列中所有小于10000的偶數(shù)和需要用到take_while,與itertools的同名函數(shù)有類似的功能,截取元素直到條件不成立:12345 fib =fibonacci fib() | where(lambdax:
15、x %2=0). | take_while(lambdax: x fib() | select(lambdax: x *2) | take_while(lambdax: x Pipe. deftake_while_idx(iterable, predicate):. foridx, x inenumerate(iterable):. ifpredicate(idx): yieldx. else: return.使用這個(gè)流處理函數(shù)獲取fib的前10個(gè)數(shù)字:12 fib() | take_while_idx(lambdax: x 10) | as_list1, 1, 2, 3, 5, 8, 13, 21, 34, 55更多的函數(shù)就不在這里介紹了,你可以查看pipe的源文件,總共600行不到的文件其
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 《基于全生命周期的電動(dòng)汽車鋰電池環(huán)境效益評(píng)價(jià)》
- 《基于酪氨酸酶抑制活性的槐耳次級(jí)代謝產(chǎn)物研究》
- 《董為杰鋼琴套曲《江西民歌五首》音樂分析及演奏處理》
- 《S公司績效考核體系優(yōu)化研究》
- 2024年度研發(fā)與技術(shù)服務(wù)合同
- 2024年錫林郭勒盟辦理客運(yùn)從業(yè)資格證考試
- 模擬卷02-2020-2021年高二化學(xué)高頻考題期末模擬卷(人教2019選擇性必修1)(原卷版)
- 2024年湖南客運(yùn)從業(yè)資格證仿真考試題庫
- 2024年安徽道路客運(yùn)輸從業(yè)資格證理論考試題
- 2024年湖北道路運(yùn)輸客運(yùn)從業(yè)資格證考試模擬試題
- GB/T 42455.2-2024智慧城市建筑及居住區(qū)第2部分:智慧社區(qū)評(píng)價(jià)
- 2024年認(rèn)證行業(yè)法律法規(guī)及認(rèn)證基礎(chǔ)知識(shí)
- YYT 0653-2017 血液分析儀行業(yè)標(biāo)準(zhǔn)
- 刑事受害人授權(quán)委托書范本
- 《文明上網(wǎng)健康成長》的主題班會(huì)
- 框架結(jié)構(gòu)冬季施工方案
- 人工智能技術(shù)在電氣自動(dòng)化控制中的應(yīng)用分析
- 醫(yī)療技術(shù)臨床應(yīng)用及新技術(shù)新項(xiàng)目管理制度考核試題及答案
- 裝配式擋土墻施工方案(完整版)
- 防炫(AG工藝)玻璃屏項(xiàng)目可行性研究報(bào)告模版
- 既有玻璃幕墻安全性鑒定技術(shù)規(guī)程
評(píng)論
0/150
提交評(píng)論