【python進階】生成器
阿新 • • 發佈:2019-01-14
參考連結:https://eastlakeside.gitbooks.io/interpy-zh/content/Generators/Iterable.html
Python中任意的物件,只要它定義了可以返回一個迭代器的__iter__方法,或者定義了可以支援下標索引的__getitem__方法(這些雙下劃線方法會在其他章節中全面解釋),那麼它就是一個可迭代物件。簡單說,可迭代物件就是能提供迭代器的任意物件。
許多Python 2裡的標準庫函式都會返回列表,而Python 3都修改成了返回生成器,因為生成器佔用更少的資源。
生成器也是一種迭代器
xrange和range的區別
xrange返回的就是一個生成器
要生成很大的數字序列的時候,用xrange會比range效能優很多,因為不需要一上來就開闢一塊很大的記憶體空間,這兩個基本上都是在迴圈的時候用:
在python3裡面,xrange已經被併到了range
也就是你列印range的型別,已經是一個生成器了。
print(range(5))
print(list(range(5)))
print(type(range(5)))
a = range(5)
print(a[0])
python3都修改返回成了生成器了
python yield
參考連結:https://www.jianshu.com/p/d09778f4e055
- 通常的for…in…迴圈中,in後面是一個數組,這個陣列就是一個可迭代物件,類似的還有連結串列,字串,檔案。它可以是mylist = [1, 2, 3],也可以是mylist = [x*x for x in range(3)]。
它的缺陷是所有資料都在記憶體中,如果有海量資料的話將會非常耗記憶體。 - 生成器是可以迭代的,但只可以讀取它一次。因為用的時候才生成。比如 mygenerator = (x*x for x in range(3)),注意這裡用到了(),它就不是陣列,而上面的例子是[]。
- 我理解的生成器(generator)能夠迭代的關鍵是它有一個next()方法,工作原理就是通過重複呼叫next()方法,直到捕獲一個異常。可以用上面的mygenerator測試。
- 帶有 yield 的函式不再是一個普通函式,而是一個生成器generator,可用於迭代,工作原理同上。
- yield 是一個類似 return 的關鍵字,迭代一次遇到yield時就返回yield後面(右邊)的值。重點是:下一次迭代時,從上一次迭代遇到的yield後面的程式碼(下一行)開始執行。
- 簡要理解:yield就是 return 返回一個值,並且記住這個返回的位置,下次迭代就從這個位置後(下一行)開始。
def yield_test(n):
for i in range(n):
yield call(i)
print("生成器裡面的數:",i)
# 做一些其它的事情
print("do something.")
print("end.")
def call(i):
return i * 2
for i in yield_test(5):
print('yield相當於return:', i)
可以看到輸出為:
計算斐波拉契數列的生成器
def fibon(n):
a = b = 1
for i in range(n):
yield a
a, b = b, a + b
函式的使用方法:
for x in fibon(100):
print(x) #這裡的x是yield返回的值,然後繼續執行生成器的下一句
這樣不用擔心使用大量的資源
測試生成器內部next函式
def generator_function():
for i in range(3):
yield i
gen = generator_function()
print(next(gen))
# Output: 0
print(next(gen))
# Output: 1
print(next(gen))
# Output: 2
print(next(gen))
可以看到最後輸出了異常,停止迭代
iter迭代器
my_string = "Yasoob"
next(my_string)
python會報錯:不是一個迭代器
my_string = "Yasoob"
my_iter = iter(my_string)
print(next(my_iter))
可以看到會輸出Y