Python 生成器,協程

2021-08-15 17:59:47 字數 2549 閱讀 6515

生成器可以簡單有效的建立龐大的可迭代物件,而不需要在直接在記憶體中建立儲存整個序列

可以使用生成器推導式或者生成器函式來建立生成器

生成器函式返回資料時使用yield語句,而不是使用return

>>> def countdown(n):

... print("counting down from %d" %n)

... while n>0:

... yield n

... n -=1

... return 'done'

...>>> c = countdown(10)    #c為乙個生成器物件

可以通過next()函式或者生成器物件的__next__()方法來獲得生成器的下乙個返回值

當計算到最後乙個元素後,沒有更多的元素時,丟擲stopinteration,生成器終止

>>> c = countdown(3)

>>> next(c)

counting down from 3

3>>> c.__next__()

2>>> next(c)

1>>> next(c)

traceback (most recent call last):

file "", line 1, in stopiteration: done

通常直接通過for迴圈來迭代生成器,並且不需要關心stopinteration

但是用for迴圈呼叫生成器時,發現拿不到生成器的return語句的返回值。

如果想要拿到返回值,必須捕獲stopinteration錯誤,返回值包含在stopinteration的value中

>>> while true:

... try:

... x = next(c)

... print(c)

... except stopiteration as e:

... print('generator return value:', e.value)

... break

...

當乙個生成器沒有全部迭代完成,但是不在使用了,可以呼叫close()方法關閉生成器,通常不必手動呼叫close()方法

c = countdown(10)

>>> next(c)

1>>> c.close()

>>> next(c)

traceback (most recent call last):

file "", line 1, in stopiteration

協程可以理解為就像生成器那樣可以暫停的函式

在函式內,當yield語句作為表示式使用,出現在賦值運算子的右邊,在向函式傳送值時函式將執行

這種生成器函式可以被稱為協程函式,而對協程函式的呼叫可以獲得協程物件

"協程"一詞可以用於協程函式和協程物件

>>> def coroutine():

... print("start coroutine")

... r = 'ok'

... while true:

... n = yield r

... print('receiver %s' % n)

...>>> c = coroutine()

>>> c.send(1)   

traceback (most recent call last):

file "", line 1, in typeerror: can't send non-none value to a just-started generator

>>> c.send(none)    #next(c)

start coroutine

'ok'

>>> c.send(1)

receiver 1

'ok'

>>> c.close()

>>> c.send(2)

traceback (most recent call last):

file "", line 1, in stopiteration

在傳送資料之前,應該呼叫c.send(none)啟動生成器或者使用next()函式,使協程執行第乙個yield之前的語句

啟動後協程會掛起,等待協程物件c的send()方法傳送值

yield語句會接收send()傳送的值,並返回yield 語句後的值

協程一般會不斷執行下去,可以通過close()方法關閉協程

我們可以使用asyncio模組中的@asyncio.coroutine裝飾器來使協程函式在呼叫時自動執行到yield語句前,而不需要提前呼叫send(none)或next()函式

具體的asyncio模組和協程的講解可以看另一篇文章

python迭代器生成器協程

迭代器有兩個基本的方法 iter 和next 把乙個類作為乙個迭代器使用需要在類中實現兩個方法iter 與next stopiteration 異常用於標識迭代的完成 class mylist object def init self self.items def iter self iter my...

python 生成器協程運算例項

一 yield執行方式 我們定義乙個如下的生成器 def put on name print hi 貨物來了,準備搬到倉庫!format name while true goods yield print 貨物 s 已經被 s搬進倉庫了。goods,name p put on bigberg 輸出g...

Python生成器函式 yield 協程應用

生成器應用 m i for i in range 5 print type m 列印結果 型別 生成器 print next m 列印結果 0 definc for i in range 5 yield i print type inc 列印結果 型別 函式 print type inc 列印結果 ...