Skip to content

Instantly share code, notes, and snippets.

@chairco
Last active June 27, 2018 03:00
Show Gist options
  • Save chairco/a4a51eef5238ed2f739541aa2f293250 to your computer and use it in GitHub Desktop.
Save chairco/a4a51eef5238ed2f739541aa2f293250 to your computer and use it in GitHub Desktop.
python3.x: generator, yield, yield from, coroutine, threading, future, asyncio

Summary about python3.x asynchronous concept

當一個 function 採取以 yield 而非 return 回傳 value 方式,那他就是一個產生器(generator)

以下範例節錄自 TP (yield a tuplip, PyConTW 2014) 連結

因為 producer() 內函 yield 關鍵字,所以是一個產生器,因此可以透過 for 迴圈 iterator 將每個值讀出來。

def producer():
    yield 0
    yield 1

g = producer()
print(type(g))

for i in g:
    print(i)

產生器可以演化成協同程序(coroutine)

PEP 342 定義了其架構,在 Python 2.5 實作將 .send() 加入到產生器,因此產生器可以透過 .send(...) 發佈資料,也就讓產生器可以成為協同程序。來看看實際例子。

def simple(a):
    print('-> Started: a=', a)
    b = yield a
    print('-> Received: b=', b)
    c = yield a + b
    print('-> Received: c=', c)

操作如何用 yield 讓產生器變成協同程序:

>>> s = simple(14)
>>> next(s)
-> Started a = 14
14
>>> s.send(28)
-> Received b = 28
42
>>> s.send(99)
-> Received c = 99
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration
  1. 產生結果,指定 s 為 simple 物件且參數 a = 14
  2. 呼叫 next() 其實是呼叫 next() 開始
  3. 將值指定給第一個 yield
  4. 印出第一個 print
  5. 產生 a 值並且暫停等候指派給 b
  6. 傳送 28, 並且指派給 b, 產生 a+b 接著暫停等候指派給 c
  7. 傳送 99, 指派給 c, 印出 print 接著協同程序終止產生 StopIteration

基本上協同程序就可以讓每個程序做自己的事,完成了再回報

async

要達成非同步需要的三個 rules:

  • non-blocking sockets
  • callback
  • event loop