天天看點

python 協程可以嵌套協程嗎_關于Python協程(Coroutine)的了解

從文法上來看,協程和生成器類似,都是在定義體中包含yield關鍵字的函數

但在

協程中

yield關鍵字通常出現在表達式的右邊:

  1. 可以産出值n(y = yield n)
  2. 也可以不産出值(y = yield),或者說是産出值為None

通過

next(coroutine)

函數

激活協程:
  1. 調用next(),傳回 yield右邊的可有可無的值或者函數值( 一般不需要next産出值,即, yield後無值,= yield ), 暫停
調用方

是通過

send(datum=None)

的方式把資料提供給協程使用:

  1. send(n)函數的傳回值為 yield右邊的值或者函數值
  2. 等号左邊的變量接受send(n)函數傳來的值
  • 可以了解為 函數next()和函數send(n)都 會執行yield右邊的 值或者函數值,
  • 但是 send(n)函數執行完 不會暫停 ,同時send(n)函數的 參數n會指派給等号左邊的變量
def 
           
python 協程可以嵌套協程嗎_關于Python協程(Coroutine)的了解

這裡的對應于

send(n)

的操作 y

= yield

實際上是

按2步進行的
  1. 第1步yield 接受send(n)函數傳來的參數值 并指派 等号=左邊 的變量,即y=n
  2. 第2步執行 yield後面的表達式或者函數并傳回值

為了檢視協程在運作過程中的四個狀态,我們引入

from inspect import getgeneratorstate
  1. GEN_CREATED :生成器建立完成,等待執行,可以了解為線程的就緒狀态
  2. GEN_RUNNING :一般看不到,可了解為線程的執行狀态
  3. GEN_SUSPENDED :在yield表達式處暫停,可了解為線程的阻塞狀态
  4. GEN_CLOSED :執行結束,可了解為線程的死亡狀态
python 協程可以嵌套協程嗎_關于Python協程(Coroutine)的了解

擷取協程的傳回值

  1. 從異常屬性中擷取:協程結束時會跟生成器一樣抛出StopIteration的異常, 傳回值 就在異常對象的 value 屬性中
  • yield from内部會自動捕獲 後面 協程StopIteration異常,并把異常對象的value屬性變成yield from的傳回值
  • yield from 的主要功能就是打開雙向通道,最外層的調用方調用 子生成器 ,同時子生成器也可使用yield from調用另一個子生成器,一直嵌套調用 直到遇到yield 表達式結束
  • send(n) 發送的值n通過yield from直接傳遞給了 最内層的子生成器 ,并在yield from處等待子生成器的傳回
python 協程可以嵌套協程嗎_關于Python協程(Coroutine)的了解

叢異常中擷取協程傳回值(1)

python 協程可以嵌套協程嗎_關于Python協程(Coroutine)的了解

叢異常中擷取協程傳回值(2)

異步IO(asyncio)

  • Python 3.4版本引入 異步IO的标準庫asyncio, 使用事件循環 驅動協程 實作并發。
  • 在asyncio庫中, 用asyncio.coroutine裝飾 用yield from來驅動協程
  • Python 3.5版本中 用async代替了 asyncio.coroutine,用 await代替了 yield from

下面展示了Python 3.4中标準庫

asyncio

中協程(coroutine)的應用

import threading import

asyncio

@asyncio.coroutine

def hello

():

print('Hello world! (%s)' % threading.currentThread())

yield from

asyncio.sleep(1)

print('Hello again! (%s)' % threading.currentThread())

loop = asyncio.get_event_loop()

tasks = [hello(), hello()]

loop.run_until_complete(asyncio.wait(tasks))

loop.close()

asyncio​www.liaoxuefeng.com

python 協程可以嵌套協程嗎_關于Python協程(Coroutine)的了解