在介紹yield前有必要先說明下Python中的迭代器(iterator)和生成器(constructor)。python
1、迭代器(iterator)函數
在Python中,for循環能夠用於Python中的任何類型,包括列表、元祖等等,實際上,for循環可用於任何「可迭代對象」,這其實就是迭代器工具
迭代器是一個實現了迭代器協議的對象,Python中的迭代器協議就是有next方法的對象會前進到下一結果,而在一系列結果的末尾是,則會引起StopIteration。任何這類的對象在Python中均可以用for循環或其餘遍歷工具迭代,迭代工具內部會在每次迭代時調用next方法,而且捕捉StopIteration異常來肯定什麼時候離開。spa
使用迭代器一個顯而易見的好處就是:每次只從對象中讀取一條數據,不會形成內存的過大開銷。code
好比要逐行讀取一個文件的內容,利用readlines()方法,咱們能夠這麼寫:orm
1 2 |
line .: line |
這樣雖然能夠工做,但不是最好的方法。由於他其實是把文件一次加載到內存中,而後逐行打印。當文件很大時,這個方法的內存開銷就很大了。對象
利用file的迭代器,咱們能夠這樣寫:接口
1 2 |
line : line |
這是最簡單也是運行速度最快的寫法,他並沒顯式的讀取文件,而是利用迭代器每次讀取下一行。內存
2、生成器(constructor)ci
生成器函數在Python中與迭代器協議的概念聯繫在一塊兒。簡而言之,包含yield語句的函數會被特意編譯成生成器。當函數被調用時,他們返回一個生成器對象,這個對象支持迭代器接口。函數也許會有個return語句,但它的做用是用來yield產生值的。
不像通常的函數會生成值後退出,生成器函數在生成值後會自動掛起並暫停他們的執行和狀態,他的本地變量將保存狀態信息,這些信息在函數恢復時將再度有效
1 2 3 4 5 6 7 8 |
gn: ... i n: ... i ... i g: ... i,, ... : : : : : |
要了解他的運行原理,咱們來用next方法看看:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
t = g t. t. t. t. t. t. Traceback most recent call last: File , line , module |
在運行完5次next以後,生成器拋出了一個StopIteration異常,迭代終止。
再來看一個yield的例子,用生成器生成一個Fibonacci數列:
1 2 3 4 5 6 7 8 9 10 |
fab: a,b = , a : a a, b = b, a+b i fab: ... i,, ... , , , , , , , , |
看到這裏應該就能理解生成器那個很抽象的概念了吧~~