python--產生器協程運算,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\install\python.exe G:/python/untitled/study4/test/double.pyProcess finished with exit code 0
當我們把一個函數通過yield轉換成產生器,直接運行函數是不會出現結果返回的。因為此時函數已經是個產生器了,我們要通過next()來取得值,並且在遇到yield時再次跳出函數。
print(type(p))#輸出<class 'generator'>
我們添加next()方法:
def put_on(name): print("Hi {}, 貨物來了,準備搬到倉庫!".format(name)) while True: goods = yield #遇到yield中斷 print("貨物[%s]已經被%s搬進倉庫了。"%(goods,name))p = put_on("bigberg")p.__next__()#輸出Hi bigberg, 貨物來了,準備搬到倉庫!
此時函數中斷在 goods = yield 的地方,當我們再次調用next()函數時,函數只會運行中斷以後的內容,即上例中的紅色字型部分。
我們再添加一個next():
def put_on(name): print("Hi {}, 貨物來了,準備搬到倉庫!".format(name)) while True: goods = yield print("貨物[%s]已經被%s搬進倉庫了。"%(goods,name))p = put_on("bigberg")p.__next__()p.__next__()#輸出Hi bigberg, 貨物來了,準備搬到倉庫!貨物[None]已經被bigberg搬進倉庫了。
我們可以看到yield並沒有給goods傳值,所有貨物是 None。
小結:
- 通過yield將函數轉換為函數,需要使用next()方法才能運行
- yield只是保留函數的中斷狀態,再次調用next()會執行yield後面的部分
- yield如果沒有傳回值,會返回一個None空值
二、send()傳值
def put_on(name): print("Hi {}, 貨物來了,準備搬到倉庫!".format(name)) while True: goods = yield print("貨物[%s]已經被%s搬進倉庫了。"%(goods,name))p = put_on("bigberg")p.__next__()p.send("瓜子")#輸出Hi bigberg, 貨物來了,準備搬到倉庫!貨物[瓜子]已經被bigberg搬進倉庫了。
小結:
- __next__()只是調用這個yield,也可以說成是喚醒yield,但是不不會給yield傳值。
- send()方法調用yield是,能給yield傳值
- 使用send()函數之前必須使用__next__(),因為先要中斷,當第二次調用時,才可傳值。
def put_on(name): print("Hi {}, 貨物來了,準備搬到倉庫!".format(name)) while True: goods = yield print("貨物[%s]已經被%s搬進倉庫了。"%(goods,name))p = put_on("bigberg")p.__next__()p.send("瓜子")p.send("花生")p.send("餅乾")p.send("牛奶")#多次調用send()Hi bigberg, 貨物來了,準備搬到倉庫!貨物[瓜子]已經被bigberg搬進倉庫了。貨物[花生]已經被bigberg搬進倉庫了。貨物[餅乾]已經被bigberg搬進倉庫了。貨物[牛奶]已經被bigberg搬進倉庫了。
三、單線程實現並行效果(協程)
import timedef put_on(name): print("Hi {}, 貨物來了,準備搬到倉庫!".format(name)) while True: goods = yield print("貨物[%s]已經被%s搬進倉庫了。"%(goods,name))def transfer(name): p = put_on('A') p2 = put_on('B') p.__next__() p2.__next__() print("%s將貨物送來了!"%name) for i in range(5): time.sleep(1) print("%s遞過來兩件貨物"%name) p.send("瓜子") p2.send("花生")transfer("bigberg")#輸出Hi A, 貨物來了,準備搬到倉庫!Hi B, 貨物來了,準備搬到倉庫!bigberg將貨物送來了!bigberg遞過來兩件貨物貨物[瓜子]已經被A搬進倉庫了。貨物[花生]已經被B搬進倉庫了。bigberg遞過來兩件貨物貨物[瓜子]已經被A搬進倉庫了。貨物[花生]已經被B搬進倉庫了。bigberg遞過來兩件貨物貨物[瓜子]已經被A搬進倉庫了。貨物[花生]已經被B搬進倉庫了。bigberg遞過來兩件貨物貨物[瓜子]已經被A搬進倉庫了。貨物[花生]已經被B搬進倉庫了。bigberg遞過來兩件貨物貨物[瓜子]已經被A搬進倉庫了。貨物[花生]已經被B搬進倉庫了。