一、生成器
求平方
//傳統方法 浪費時間
square_table = []
for i in range(10000):
square_table.append(i*i)
for i in range(10):
print (square_table[i])
生成器(到使用的時候才做真正的計算,節省時間和空間)
square_generator = (x*x for x in range(50000))//range(50000)爲生成器
for i in range(10):
print(next(square_generator))
示例:斐波那契數列
def fib(limit):
n,a,b = 0,0,1
while n<limit:
#print(b)
yield b
a,b = b,a+b
n += 1
return 'done'
import traceback
f = fib(5)
try:
print(next(f))
except StopITeration:
traceback.print_exc()
for i in fib(5):
print(i)
二、yeild關鍵字
一個帶有 yield 的函數就是一個 generator,它和普通函數不同,生成一個 generator 看起來像函數調用,但不會執行任何函數代碼,直到對其調用 next()(在 for 循環中會自動調用 next())纔開始執行。雖然執行流程仍按函數的流程執行,但每執行到一個 yield 語句就會中斷,並返回一個迭代值,下次執行時從 yield 的下一個語句繼續執行。看起來就好像一個函數在正常執行的過程中被 yield 中斷了數次,每次中斷都會通過 yield 返回當前的迭代值。
yield 的好處是顯而易見的,把一個函數改寫爲一個 generator 就獲得了迭代能力,比起用類的實例保存狀態來計算下一個 next() 的值,不僅代碼簡潔,而且執行流程異常清晰。
詳情請見:https://www.ibm.com/developerworks/cn/opensource/os-cn-python-yield/
如何判斷一個函數是否是一個特殊的 generator 函數?可以利用 isgeneratorfunction 判斷:
from inspect import isgeneratorfunction
isgeneratorfunction(fab)
//True
三、迭代器(惰性計算,生成器是迭代器的一種)
迭代器持有一個內部狀態的字段,用於記錄下次迭代返回值,它實現了next和iter方法,迭代器不會一次性把所有元素加載到內存,而是需要的時候才生成返回結果。
那麼什麼迭代器呢?它是一個帶狀態的對象,他能在你調用next()方法的時候返回容器中的下一個值,任何實現了iter和next()(python2中實現next())方法的對象都是迭代器,iter返回迭代器自身,next返回容器中的下一個值,如果容器中沒有更多元素了,則拋出StopIteration異常,至於它們到底是如何實現的這並不重要。
from collections import Iterable
from collections import Iterator
//判斷列表和字典是否是可迭代的,結果返回True
print(isinstance([1,2,3],Iterable))//True
print(isinstance({},Iterabel))//True
print(isinstance(123,Iterabel))//False
print(isinstance(‘abc',Iterabel))//True
print(isinstance([1,2,3],Iterator))//數組是可迭代的,但不是可迭代器
g = (x*x for x in range(10))
print(type(g))
print(isinstance(g,Iterable))//True,是可迭代的,便可以用for循環來打印
for i in g:
print(i)
//判斷斐波那契函數是否是迭代器
def fib(limit):
n,a,b = 0,0,1
while n<limit:
#print(b)
yield b
a,b = b,a+b
n += 1
return 'done'
f = fib(6)
print(type(f))
print(isinstance(f,iterable))//True
print(isinstance(f,iterator))//True
for i in f:
print(i)
推薦一篇解釋十分詳細的文章:http://python.jobbole.com/87805/