Python之協程(coroutine)
標簽(空格分隔): Python進階
coroutine和generator的區別
generator是數據的產生者。即它pull data 通過 iteration
coroutine是數據的消費者。它push data into pipeline 通過 send
generator的通常用法
generator的作用是可以作為data pipeline使用.
例如可以使用coroutine來做filter,
或者多路的broadcast。
generator通常是yield和for的運用。
示例代碼1:
def fib():
a, b = 0, 1
while True:
yield a
a, b = b, a+b
for i in fib():
print(i)
用yield接收data,通過for循環將每一步data輸出。
下面介紹coroutine, 它的yield接收外部value,而不是保存內部value。
def grep(pattern):
print("Searching for", pattern)
while True:
line = (yield)
if pattern in line:
print line
此處的 yield並不包含任何value,它接受外部.send()方法傳過來的value.
search = grep('coroutine')
next(search)
# Output: Searching for coroutine
search.send("I love you")
search.send("Don't you love me?")
search.send("I love coroutines instead!")
# Output: I love coroutines instead!
search.close()
先通過next(),start這個coroutine.
之后每一次調用send(),將參數通過yield傳入line中。同時相當於自動運行.next()到下一個value. 最終調用.close()關閉這個協程。
示例1:作為filter使用
import time
def follow(thefile, target):
thefile.seek(0,2) # Go to the end of the file
while True:
line = thefile.readline()
if not line:
time.sleep(0.1) # Sleep briefly
continue
target.send(line)
@coroutine
def printer():
while True:
line = (yield)
print line
@coroutine
def grep(pattern,target):
while True:
line = (yield) # Receive a line
if pattern in line:
target.send(line) # Send to next stage
f = open("access-log")
follow(f,grep('python',printer()))
dataflow如下:###
follow將file中的每一行讀取,send到coroutine中,grep查找匹配的line,send到下一個coroutine中,printer接收send過來的data,並且輸出。 完成整個filter的流程。
follow()-> grep() : send()
grep() -> printer():send()
示例2:作為broadcasting使用
@coroutine
def broadcast(targets):
while True:
item = (yield)
for target in targets:
target.send(item)
f = open("access-log")
p = printer()
follow(f,
broadcast([grep('python',p),
grep('ply',p),
grep('swig',p)])
)
這樣就將不同的pattern傳入到了不同的coroutine中去,達到了broadcast的目的。
follow-> broadcast: send()
broadcast -> grep('python'): send()
broadcast -> grep('ply') : send()
broadcast -> grep('swig') : send()
grep('python') -> printer:
grep('ply')-> printer:
grep('swig')-> printer:
關於coroutine的更多用法,可見pdf:
http://www.dabeaz.com/coroutines/Coroutines.pdf