通過列表生成式,我們可以直接建立乙個列表。但是,受到記憶體限制,列表容量肯定是有限的。而且,建立乙個包含100萬個元素的列表,不僅占用很大的儲存空間,如果我們僅僅需要訪問前面幾個元素,那後面絕大多數元素占用的空間都白白浪費了。
所以,如果列表元素可以按照某種演算法推算出來,那我們是否可以在迴圈的過程中不斷推算出後續的元素呢?這樣就不必建立完整的list,從而節省大量的空間。在python中,這種一邊迴圈一邊計算的機制,稱為生成器(generator)。
生成器是乙個包含了特殊關鍵字yield的函式。當被呼叫的時候,生成器函式返回乙個生成器。可以使用send,throw,close方法讓生成器和外界互動。
生成器也是迭代器,但是它不僅僅是迭代器,擁有next方法並且行為和迭代器完全相同。所以生成器也可以用於python的迴圈中。
生成器是這樣乙個函式,它記住上一次返回時在函式體中的位置。對生成器函式的第二次(或第 n 次)呼叫跳轉至該函式中間,而上次呼叫的所有區域性變數都保持不變。
生成器不僅「記住」了它的資料狀態;生成器還「記住」了它在流控制構造(在命令式程式設計中,這種構造不只是資料值)中的位置。
生成器是乙個函式,而且函式的引數都會保留。
迭代到下一次的呼叫時,所使用的引數都是第一次所保留下的,即是說,在整個所有函式呼叫的引數都是第一次所呼叫時保留的,而不是新建立的。
當你問生成器要乙個數時,生成器會執行,直至出現 yield 語句,生成器把 yield 的引數給你,之後生成器就不會往下繼續執行。 當你問他要下乙個數時,他會從上次的狀態開始執行,直至出現yield語句,把引數給你,之後停下。如此反覆,直至退出函式。
在python中,當你定義乙個函式,使用了yield關鍵字時,這個函式就是乙個生成器,它的執行會和其他普通的函式有很多不同,函式返回的是乙個物件,而不是你平常所用return語句那樣,能得到結果值。如果想取得值,得呼叫next()函式。
例子一:
例子二:#! /usr/bin/env python
#coding=utf-8
deffib
():
a,b = 0,1
while
1: yield b
a,b = b,a+b
#yield a
if __name__ == '__main__':
f = fib() #函式返回的是乙個物件
for i in range(6):
print f.next()#呼叫next()函式取得值
程式執行:def
fib(max):
a, b = 1, 1
while a < max:
yield a
a, b = b, a+b
從前面的執行機制描述中,可以獲知,程式執行到yield這行時,就不會繼續往下執行。而是返回乙個包含當前函式所有引數狀態的iterator物件。目的就是為了第二次被呼叫時,能夠訪問到函式所有的引數值都是第一次訪問時的值,而不是重新賦值。for n in fib(15):
print n
程式第一次呼叫時:
程式第二次呼叫時:def
fib(max):
a, b = 1, 1
while a < max:
yield a #這時a,b值分別為1,1,當然,程式也在執行到這時,返回
a, b = b, a+b
從前面可知,第一次呼叫時,a,b=1,1,那麼,我們第二次呼叫時(其實就是呼叫第一次返回的iterator物件的next()方法),程式跳到yield語句處,
執行a,b = b, a+b語句,此時值變為:a,b = 1, (1+1) => a,b = 1, 2
程式繼續while迴圈,當然,再一次碰到了yield a 語句,也是像第一次那樣,儲存函式所有引數的狀態,返回乙個包含這些引數狀態的iterator物件。
等待第三次的呼叫….
通過上面的分析,可以依次類推的展示了yield的詳細執行過程!
而將上述過程用迭代器實現如下:
結果:#! /usr/bin/env python
#coding=utf-8
class
fib:
def__init__
(self, max):
self.max = max
def__iter__
(self):
self.a = 0
self.b = 1
return self
defnext
(self):
fib = self.a
if fib > self.max:
raise stopiteration
self.a, self.b = self.b, self.a + self.b
return fib
if __name__ == '__main__':
for f in fib(6):
print f
很顯然,沒有生成器簡潔,通過使用生成器的語法,可以免去寫迭代器類的繁瑣**。011
235
Python之生成器(yield)
這裡是一段防爬蟲文字,請讀者忽略。本文原創首發於csdn,作者idys 部落格首頁 生成器函式 迭代器一定是可迭代物件,可迭代物件不一定是迭代器 def inc for i in range 5 yield i print type inc print type inc x inc print ty...
python中生成器yield
def yield demo for x in range 3 yield x print 生成器後一行 a yield demo print a 這裡的a是乙個生成器物件 可以用for迴圈來遍歷生成器物件裡的元素 for i in a print i 那麼yield的工作過程是怎麼樣的呢?可以通過...
生成器 PHP的生成器yield 原創
在php 5.5中,php多了乙個新的特性,那就是生成器 generator 生成器提供了一種更簡單的方法來實現簡單的物件迭代。下面的manual的引用 生成器提供了一種更容易的方法來實現簡單的物件迭代,相比較定義類實現 iterator 介面的方式,效能開銷和複雜性大大降低。生成器允許你在 for...