生成器(constructor)生成器函數(shù)在Python中與迭代器協(xié)議的概念聯(lián)系在一起。包含yield語句的函數(shù)會被特地編譯成生成器 !!! 當(dāng)函數(shù)被調(diào)用時,他們返回一個生成器對象,這個對象支持迭代器接口。 不像一般的函數(shù)會生成值后退出,生成器函數(shù)在生成值后會自動掛起并暫停他們的執(zhí)行和狀態(tài),他的本地變量將保存狀態(tài)信息,這些信息在函數(shù)恢復(fù)時將再度有效 創(chuàng)建生成器方式有兩種: 方法一:
方法二:
例子:
要了解他的運行原理,我們來用next方法看看:
在運行完5次next之后,生成器拋出了一個StopIteration異常,迭代終止。 send(msg) 與 next() 了解了next()如何讓包含yield的函數(shù)執(zhí)行后,我們再來看另外一個非常重要的函數(shù)send(msg)。 其實next()和send()在一定意義上作用是相似的,區(qū)別是send()可以傳遞yield表達(dá)式的值進(jìn)去,而next()不能傳遞特定的值,只能傳遞None進(jìn)去。因此,我們可以看做 c.next() 和 c.send(None) 作用是一樣的。
需要注意的是,第一次調(diào)用時,請使用next()語句或是send(None),不能使用send發(fā)送一個非None的值,否則會出錯的,因為沒有yield語句來接收這個值。 send(msg) 和 next()是有返回值的,它們的返回值很特殊,返回的是yield表達(dá)式的參數(shù) ! 執(zhí)行順序是:遇到y(tǒng)ield 先返回值,等下次再進(jìn)入時再用 msg 進(jìn)行賦值?。。?/p> 再來看一個yield的例子,用生成器生成一個Fibonacci數(shù)列:
另一個 yield 的例子來源于文件讀取。
迭代器(iterator)for循環(huán)可以用于Python中的任何類型,包括列表、元祖等等,實際上,for循環(huán)可用于任何“可迭代對象”! 迭代器是一個實現(xiàn)了迭代器協(xié)議的對象,Python中的迭代器協(xié)議就是有next方法的對象會前進(jìn)到下一結(jié)果,而在一系列結(jié)果的末尾是,則會引發(fā)StopIteration。 任何這類的對象在Python中都可以用for循環(huán)或其他遍歷工具迭代,迭代工具內(nèi)部會在每次迭代時調(diào)用next方法,并且捕捉StopIteration異常來確定何時離開。 使用迭代器一個顯而易見的好處就是:每次只從對象中讀取一條數(shù)據(jù),不會造成內(nèi)存的過大開銷。 注意: 判斷迭代器的條件是:
所有的生成器都是迭代器! 迭代器例子: 比如要逐行讀取一個文件的內(nèi)容,利用readlines()方法,我們可以這么寫:
這樣雖然可以工作,但不是最好的方法。因為他實際上是把文件一次加載到內(nèi)存中,然后逐行打印。當(dāng)文件很大時,這個方法的內(nèi)存開銷就很大了。 利用file的迭代器,我們可以這樣寫:
這是最簡單也是運行速度最快的寫法,他并沒顯式的讀取文件,而是利用迭代器每次讀取下一行。 for 循環(huán)實質(zhì):
![]()
可迭代對象(iterable)判斷條件:內(nèi)部具有 __iter__ 方法
|
|