通過列表表達式可以直接生成列表,不過列表一旦生成就需要為所有元素分配內存,有時候會很消耗資源。
所以,如果列表元素可以按照某種算法推算出來,這樣就不必創建完整的list,從而節省大量的內存空間。
在Python中,這種一邊循環一邊計算的機制,稱為生成器(Generator)。
創建列表
法一: test = range(10) print type(test) # <type 'list'> 法二: test = [item for item in range(10)] print type(test) # <type 'list'>
創建生成器
test = (item for item in range(10)) print type(test) # <type 'generator'>
生成器是一個可以自動推導后續元素的對象,為了得到其元素,我們可以直接通過 next() 方法:
test = (item for item in range(10)) print type(test) print test.next() print test.next() print test.next() # <type 'generator'> # 0 # 1 # 2
另外一種方式是用 for 可以直接迭代生成器的所有元素:
test = (item for item in range(10)) print type(test) for item in test: print item # <type 'generator'> # 0 # 1 # 2 # 3 # 4 # 5 # 6 # 7 # 8 # 9
注意,每一次調用 next() 都使得生成器推導出下一個元素,使得生成器的元素減少:
test = (item for item in range(10)) print type(test) print test.next() print test.next() #至此,生成器中只還有8個元素 for index, item in enumerate(test): print index, '=', item # <type 'generator'> # 0 # 1 # 0 = 2 # 1 = 3 # 2 = 4 # 3 = 5 # 4 = 6 # 5 = 7 # 6 = 8 # 7 = 9
用函數創建生成器
如果函數中包含 yield ,那么該函數就變成了一個生成器。
函數類型的生成器的特點是:在每次調用 next() 的時候執行,遇到 yield 語句就完成一個元素的推導並返回,再次執行 next() 時從上次返回的 yield 語句處繼續向后執行:
def func(): def func(): print 'one' print 'one' yield 1 yield 1 print 'two' print 'two' yield 2 yield 2 print 'three' print 'three' yield 3 yield 3 test = func() test = func() test.next() test.next() test.next() test.next() for item in test: for item in test: print item item # one # one # two # two # three # three # 3 # 此時並沒有打印生成器的最后一個元素值
生成器函數應用示例
用生成器產生斐波拉契數列(Fibonacci),除第一個和第二個數外,任意一個數都可由前兩個數相加得到:
直接打印元素:
def func(max): before = 0 after = 1 while after < max: print before before, after = after, before + after func(10) # 0 # 1 # 1 # 2 # 3 # 5
使用列表保存結果:
def func(max): list = [] before = 0 after = 1 while after < max: list.append(before) before, after = after, before + after return list my_list = func(10) print my_list # [0, 1, 1, 2, 3, 5]
使用生成器:
def func(max): before = 0 after = 1 while after < max: yield before before, after = after, before + after test = func(10) print test for item in test: print item # <generator object func at 0x7f228e111730> # 0 # 1 # 1 # 2 # 3 # 5
