什么是生成器转唉?
生成器就是一種可循環(huán)可計(jì)算的機(jī)制
創(chuàng)建生成器方法1
要?jiǎng)?chuàng)建一個(gè)生成器,有很多種方法稳捆。第一種方法很簡單,只要把一個(gè)列表生成式的[ ]改成( )
創(chuàng)建L和G的區(qū)別僅在于最外層的[ ]和( )麦轰,L是一個(gè)列表乔夯,而G是一個(gè)生成器。我們可以直接打印出L的每一個(gè)元素款侵,但我們怎么打印出G的每一個(gè)元素呢末荐?如果要一個(gè)一個(gè)打印出來,可以通過next()函數(shù)獲得生成器的下一個(gè)返回值:
創(chuàng)建生成器方法2
generator非常強(qiáng)大新锈。如果推算的算法比較復(fù)雜甲脏,用類似列表生成式的for循環(huán)無法實(shí)現(xiàn)的時(shí)候,還可以用函數(shù)來實(shí)現(xiàn)妹笆。
比如块请,著名的斐波拉契數(shù)列(Fibonacci),除第一個(gè)和第二個(gè)數(shù)外拳缠,任意一個(gè)數(shù)都可由前兩個(gè)數(shù)相加得到:
仔細(xì)觀察墩新,可以看出,fib函數(shù)實(shí)際上是定義了斐波拉契數(shù)列的推算規(guī)則窟坐,可以從第一個(gè)元素開始海渊,推算出后續(xù)任意的元素绵疲,這種邏輯其實(shí)非常類似generator。
也就是說臣疑,上面的函數(shù)和generator僅一步之遙盔憨。要把fib函數(shù)變成generator,只需要把print(b)改為yield b就可以了:
在上面fib的例子讯沈,我們在循環(huán)過程中不斷調(diào)用yield郁岩,就會(huì)不斷中斷。當(dāng)然要給循環(huán)設(shè)置一個(gè)條件來退出循環(huán)芙盘,不然就會(huì)產(chǎn)生一個(gè)無限數(shù)列出來驯用。同樣的,把函數(shù)改成generator后儒老,我們基本上從來不會(huì)用next()來獲取下一個(gè)返回值蝴乔,而是直接使用for循環(huán)來迭代:
但是用for循環(huán)調(diào)用generator時(shí),發(fā)現(xiàn)拿不到generator的return語句的返回值驮樊。如果想要拿到返回值薇正,必須捕獲StopIteration錯(cuò)誤,返回值包含在StopIteration的value中:
send
例子:執(zhí)行到y(tǒng)ield時(shí)囚衔,gen函數(shù)作用暫時(shí)保存挖腰,返回i的值;temp接收下次c.send("python"),send發(fā)送過來的值练湿,c.next()等價(jià)c.send(None)
使用next方法
使用__next__()方法
使用send方法
實(shí)現(xiàn)多任務(wù)
總結(jié)
生成器是這樣一個(gè)函數(shù)猴仑,它記住上一次返回時(shí)在函數(shù)體中的位置。對(duì)生成器函數(shù)的第二次(或第n次)調(diào)用跳轉(zhuǎn)至該函數(shù)中間肥哎,而上次調(diào)用的所有局部變量都保持不變辽俗。
生成器不僅“記住”了它數(shù)據(jù)狀態(tài);生成器還“記住”了它在流控制構(gòu)造(在命令式編程中篡诽,這種構(gòu)造不只是數(shù)據(jù)值)中的位置崖飘。
生成器的特點(diǎn):
1.節(jié)約內(nèi)存
2.迭代到下一次的調(diào)用時(shí),所使用的參數(shù)都是第一次所保留下的杈女,即是說朱浴,在整個(gè)所有函數(shù)調(diào)用的參數(shù)都是第一次所調(diào)用時(shí)保留的,而不是新創(chuàng)建的