Python之協程(coroutine)


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



免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM