生成器
生成器是一類特殊的疊代器
将每次疊代傳回數值的return換成了yield,此時新定義的函數便不再是函數,而是一個生成器了。簡單來說:隻要在def中有yield關鍵字的 就稱為 生成器
In [30]: def fib(n):
....: current = 0
....: num1, num2 = 0, 1
....: while current < n:
....: num = num1
....: num1, num2 = num2, num1+num2
....: current += 1
....: yield num
....: return 'done'
In [39]: g = fib(5)
In [40]: while True:
....: try:
....: x = next(g)
....: print("value:%d"%x)
....: except StopIteration as e:
....: print("生成器傳回值:%s"%e.value)
....: break
....:
value:1
value:1
value:2
value:3
value:5
生成器傳回值:done
生成器在yield時,将對應的值送到主函數調用next()的x中,暫停生成器,同時保留原來的資料參數。等到再次執行next()時,生成器在原來暫停的位置,繼續執行。
總結
總結
- 使用了yield關鍵字的函數不再是函數,而是生成器。(使用了yield的函數就是生成器)
- yield關鍵字有兩點作用:
- 儲存目前運作狀态(斷點),然後暫停執行,即将生成器(函數)挂起
- 将yield關鍵字後面表達式的值作為傳回值傳回,此時可以了解為起到了return的作用
- 可以使用next()函數讓生成器從斷點處繼續執行,即喚醒生成器(函數)
- Python3中的生成器可以使用return傳回最終運作的傳回值,而Python2中的生成器不允許使用return傳回一個傳回值(即可以使用return從生成器中退出,但return後不能有任何表達式)。
使用send喚醒
使用send喚醒
我們除了可以使用next()函數來喚醒生成器繼續執行外,還可以使用send()函數來喚醒執行。使用send()函數的一個好處是可以在喚醒的同時向斷點處傳入一個附加資料。
In [10]: def gen():
....: i = 0
....: while i<5:
....: temp = yield i
....: print(temp)
....: i+=1
....:
使用send
In [43]: f = gen()
In [44]: next(f)
Out[44]: 0
In [45]: f.send('haha')
haha
Out[45]: 1
next将yield的i值傳到調用next指向的變量,然後調用send将’haha’傳入給temp,同時喚醒生成器,從next暫停處順序執行,再次執行到yield處,将i值傳到調用send指向的變量。