還記得在迭代器里我們說(shuō)為什么將列表轉(zhuǎn)為迭代器么,?(傳送門) 小明:因?yàn)榱斜硖蟮脑捳加脙?nèi)存太大,做成迭代器可以節(jié)省空間,,用的時(shí)候再拿出部分 是的,,今天要講的生成器是不會(huì)把結(jié)果保存在一個(gè)系列中,而是保存生成器的狀態(tài),。 在每次進(jìn)行迭代時(shí)返回一個(gè)值,,直到遇到StopIteration異常結(jié)束。 見過(guò)這種東西吧: 你可以認(rèn)為每一杯飲料就是一個(gè)生成的對(duì)象,,我不會(huì)一次倒出所有的飲料 而是要喝的時(shí)候去倒出一杯(也就是需要的時(shí)候生成一個(gè)) 簡(jiǎn)單方法創(chuàng)建生成器我們看個(gè)例子: 我們發(fā)現(xiàn),,當(dāng)要生成的list非常大時(shí),拋出異常,,存儲(chǔ)報(bào)錯(cuò),。 那怎樣生成這種巨大的list呢? 你親手試一下,,發(fā)現(xiàn)瞬間程序就運(yùn)行結(jié)束了 我們看到,,b是一個(gè)generator,也就是生成器模式 你應(yīng)該已經(jīng)注意到,,生成器的創(chuàng)建很簡(jiǎn)單,,將列表生成式的中括號(hào)改成小括號(hào)即可 注意:這里說(shuō)的不是列表,因?yàn)榱斜淼闹欣ㄌ?hào)改成小括號(hào)是元組,! 那我們?cè)趺瓷梢粋€(gè)內(nèi)容呢,? 和之前的迭代器相同,使用next()函數(shù)即可: 直到最后會(huì)拋出異常,,也就是到達(dá)了生成器的末端了 函數(shù)進(jìn)化為生成器還記得函數(shù)的定義么,? 我們?cè)谥坝眠f歸定義了一個(gè)斐波那契數(shù)列 現(xiàn)在我們定義一個(gè)新的函數(shù)來(lái)生成斐波那契數(shù)列的第n項(xiàng) 為了實(shí)現(xiàn)后一項(xiàng)等于前兩項(xiàng)之和使用了a,b = b,,a+b 為什么這樣寫,,留給大家思考~ 提示:可以輸入n=3,自己感受一下調(diào)用函數(shù)過(guò)程中a和b的變化 值得注意的是,,這個(gè)函數(shù),當(dāng)n=0時(shí)返回的是1,,而不是正確的0 所以我們對(duì)其進(jìn)行修改: 在循環(huán)之前,,加了一個(gè)判斷 小明:老濕!你這個(gè)說(shuō)的還是函數(shù)啊,,和生成器有啥關(guān)系,?說(shuō)好的函數(shù)進(jìn)化成生成器呢? 好的,,我們看看函數(shù)怎么進(jìn)化為生成器,! 我們把函數(shù)中的return換成yield 函數(shù)就進(jìn)化成了生成器,當(dāng)我們調(diào)用時(shí),發(fā)現(xiàn)返回的是生成器對(duì)象 為了拿到數(shù)據(jù),,我們應(yīng)該怎么做呢,? 小紅:老師,是不是可以試試next()函數(shù)呢,? 對(duì),,不過(guò)在此之前,我們先要用一個(gè)變量去接收這個(gè)生成器對(duì)象 并且為了觀察生成器的特點(diǎn),,我們對(duì)函數(shù)進(jìn)行修改,! 仔細(xì)看好: 當(dāng)我們使用next(a)對(duì)生成器操作一次時(shí),會(huì)返回循環(huán)一次的值 也就是在yield處結(jié)束本次運(yùn)行 但它的特點(diǎn)就是下次使用next(a)時(shí),,接著上次的斷點(diǎn)繼續(xù)運(yùn)行,,直到下一個(gè)yield 不斷使用next(a),直到運(yùn)行到生成器結(jié)尾處,,如下圖: 可能你對(duì)他的運(yùn)行過(guò)程還不是特別清晰 我們加上print輸出來(lái)徹底搞懂他的運(yùn)行過(guò)程: 發(fā)現(xiàn)每次返回值都是在yield的地方了吧~ 小結(jié):
使用for循環(huán)調(diào)用生成器我們使用next()去遍歷生成器的時(shí)候,,我們不知道什么時(shí)候會(huì)結(jié)束 而結(jié)束后再使用next()會(huì)拋出異常 因?yàn)樯善鲗儆诘?/p> 所以我們可以使用for循環(huán)去調(diào)用生成器 與next()等價(jià)的方式send()強(qiáng)勢(shì)入場(chǎng)我們先看一個(gè)例子: 發(fā)現(xiàn)每次運(yùn)行,除了返回下一個(gè),,還會(huì)打印出None 觀察代碼,,注意 item = yield i 這句 首先執(zhí)行等號(hào)右邊的,yield返回,,此時(shí),,返回生成器一個(gè)對(duì)象,并且中斷 在下次使用 f.__next__( )時(shí)候,,并沒(méi)有傳內(nèi)容進(jìn)去,,所以可以認(rèn)為yield i 這整個(gè)賦值給item的為None 所以item打印出為None 為了做個(gè)比較,引入send() send()可以看做next()的增強(qiáng)版 除了可以使用next()功能 還能傳入一個(gè)值到上次yield斷開地方的整體表達(dá)式(這里傳給是yield i) send()的坑: 這是為什么呢,? 6 send()退化為next() 小紅:老師,,我想了兩天終于想到了! 哦,?你說(shuō)說(shuō) 小紅:因?yàn)?f.send()取生成器第一個(gè)對(duì)象,,并且傳入了一個(gè)參數(shù)‘Python’ 但是,并沒(méi)有變量去接收這個(gè)參數(shù),!所以報(bào)錯(cuò)了,! 是的,之前我們的代碼是這樣的: 注意,,我們調(diào)用第一個(gè)對(duì)象使用next,,并沒(méi)有傳入?yún)?shù),! 而第二次使用send調(diào)用下一個(gè)對(duì)象時(shí)候,傳入的參數(shù)相當(dāng)于代替了yield i 也就是賦值給了item,,所以沒(méi)報(bào)錯(cuò) 小明:老濕,,你說(shuō)send是加強(qiáng)版的next,我想給send退化到next,,可以么,? 這個(gè)嘛,是可以的,!小明你試試,! 小明:大家都退后!我要裝逼了,! 小明:不傳參數(shù)竟然不行?。?! 小明啊,,應(yīng)該是這樣的! 傳入None才對(duì),! 小明:我不服,!老濕,你說(shuō)這生成器很厲害,,具體有啥應(yīng)用呢,?學(xué)了沒(méi)用豈不是很雞肋? 這個(gè)嘛,!其實(shí)是有用的,,我先劇透一下! 多任務(wù)——協(xié)程我們先介紹一下多任務(wù) 多任務(wù)處理是指用戶可以在同一時(shí)間內(nèi)運(yùn)行多個(gè)應(yīng)用程序,每個(gè)應(yīng)用程序被稱作一個(gè)任務(wù) 簡(jiǎn)單點(diǎn)說(shuō),,就是 你現(xiàn)在可能邊看這篇文章邊聽著音樂(lè) 而看文章是一個(gè)任務(wù)(這里的任務(wù)指正在做的事情) 聽音樂(lè)也是一個(gè)任務(wù) 你同時(shí)在做這兩件事 就是多任務(wù)啦 電腦和人還是不一樣的 我們今天講一下協(xié)程來(lái)完成多任務(wù)(之后還會(huì)講到線程,、進(jìn)程來(lái)完成多任務(wù)) 考慮一個(gè)工廠流水線 A機(jī)器每次將一件貨物放入箱子 B機(jī)器每次將A機(jī)器的箱子封箱打包 為了不產(chǎn)生問(wèn)題,必須A完成一個(gè),,B接著完成一個(gè) 并且看起來(lái)兩個(gè)任務(wù)是同時(shí)執(zhí)行的,! 在Python中可以用生成器實(shí)現(xiàn)簡(jiǎn)單的協(xié)程: 我們來(lái)看這個(gè)程序,先定義了兩個(gè)生成器(不是函數(shù)哦~原因在之前課程講過(guò)) 當(dāng)我們?cè)趙hile主程序中,,先使用f1.__next__( )調(diào)用生成器func1,,因?yàn)閒un1的循環(huán)條件始終為真 所以先打印(執(zhí)行裝入操作)然后遇到 yield 退出生成器func1,,回到主程序 接著執(zhí)行f2.__next__( )調(diào)用生成器func2,像之前調(diào)用func1一樣,,先打?。▓?zhí)行打包操作) 然后遇到y(tǒng)ield退出生成器func2,,回到主程序 因?yàn)橹鞒绦蜓h(huán)條件始終為真,所以繼續(xù)像之前一樣,,接著使用f1.__next__( )調(diào)用生成器func1,。。,。 如此往復(fù),。。,。 我是使用打斷來(lái)停止程序執(zhí)行的,,不然會(huì)不斷執(zhí)行下去 由于兩個(gè)生成器(任務(wù))交替執(zhí)行,很快 就像在多任務(wù)執(zhí)行 所以,,通俗理解看上去同時(shí)執(zhí)行的就是多任務(wù)~ 小明:竟然有這種操作,! 今天作業(yè):敲一遍代碼,理解一下兩種生成器創(chuàng)建方式 自己不敲代碼永遠(yuǎn)學(xué)不會(huì)寫代碼 下課 人生苦短,,我選Python 未完待續(xù),,連載中...... |
|
來(lái)自: 藍(lán)天cipvfv9gyo > 《IT相關(guān)》