1. 程式人生 > >【python進階】生成器

【python進階】生成器

參考連結: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

  1. 通常的for…in…迴圈中,in後面是一個數組,這個陣列就是一個可迭代物件,類似的還有連結串列,字串,檔案。它可以是mylist = [1, 2, 3],也可以是mylist = [x*x for x in range(3)]。
    它的缺陷是所有資料都在記憶體中,如果有海量資料的話將會非常耗記憶體。
  2. 生成器是可以迭代的,但只可以讀取它一次。因為用的時候才生成。比如 mygenerator = (x*x for x in range(3)),注意這裡用到了(),它就不是陣列,而上面的例子是[]。
  3. 我理解的生成器(generator)能夠迭代的關鍵是它有一個next()方法,工作原理就是通過重複呼叫next()方法,直到捕獲一個異常。可以用上面的mygenerator測試。
  4. 帶有 yield 的函式不再是一個普通函式,而是一個生成器generator,可用於迭代,工作原理同上。
  5. yield 是一個類似 return 的關鍵字,迭代一次遇到yield時就返回yield後面(右邊)的值。重點是:下一次迭代時,從上一次迭代遇到的yield後面的程式碼(下一行)開始執行。
  6. 簡要理解: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