摘要:協(xié)程定義協(xié)程是指一個(gè)過(guò)程,這個(gè)過(guò)程與調(diào)用方協(xié)作,產(chǎn)出由調(diào)用方提供的值。當(dāng)?shù)玫娇刂茩?quán)時(shí),會(huì)阻塞,同時(shí)等待終止。終止協(xié)程的方法該方法致使生成器在暫停的表達(dá)式處拋出異常。
協(xié)程
定義:協(xié)程是指一個(gè)過(guò)程,這個(gè)過(guò)程與調(diào)用方協(xié)作,產(chǎn)出由調(diào)用方提供的值。(協(xié)程中必定含有一條yield語(yǔ)句)
協(xié)程與生成器類(lèi)似,都是定義體內(nèi)包含yield關(guān)鍵字的函數(shù)。不過(guò),在協(xié)程中,yield通常出現(xiàn)在表達(dá)式的右邊(例如,data = yield),可以產(chǎn)出值,也可以不產(chǎn)出。
生成器不可以返回值,如果生成器中給return語(yǔ)句提供值,會(huì)拋出SyntaxError異常;
python新引入yield from 語(yǔ)句,可以把復(fù)雜的生成器重構(gòu)成小型的嵌套生成器,省去了大量樣板代碼。
三個(gè)方法:. send() 方法,可以讓調(diào)用方給協(xié)程發(fā)送數(shù)據(jù),發(fā)送的數(shù)據(jù)會(huì)成為協(xié)程函數(shù)中 yield 表達(dá)式的值。
.throw() 方法,可以讓調(diào)用方拋出異常
.close() 方法,可以讓調(diào)用方終止協(xié)程
四個(gè)狀態(tài):"GEN_CREATED" 等待開(kāi)始執(zhí)行
"GEN_RUNNING" 解釋器正在執(zhí)行
"GEN_SUSPENDED" 在yield表達(dá)式處暫停
"GEN_CLOASED" 執(zhí)行結(jié)束
協(xié)程只能處于這四個(gè)狀態(tài)中的一個(gè),當(dāng)前狀態(tài)可以由 inspect.getgeneratorstate(...)函數(shù)獲取
因?yàn)閟end() 方法的參數(shù)會(huì)成為暫停的yield表達(dá)式的值,所以,僅當(dāng)協(xié)程處于暫停狀態(tài)時(shí)才能調(diào)用send()方法
協(xié)程需要被預(yù)激,預(yù)激是通過(guò)next()函數(shù)進(jìn)行
給協(xié)程添加預(yù)激裝飾器 functools.wraps(),可以省去協(xié)程的預(yù)激過(guò)程。
yield from在生成器gen中使用yield from subgen()時(shí),subgen()會(huì)得到當(dāng)前的控制權(quán),把產(chǎn)出的值傳給gen的調(diào)用方,即調(diào)用方可以直接跳過(guò)gen控制subgen。當(dāng)subgen得到控制權(quán)時(shí),gen會(huì)阻塞,同時(shí)等待subgen終止。
一個(gè)小例子:
def chain(*iters): for iter in iters: yield from iter lst_1 = "abc" lst_2 = "987" print(list(chain(lst_1, lst_2)))
運(yùn)行結(jié)果:
["a", "b", "c", "9", "8", "7"]
這個(gè)例子還可以改寫(xiě)為:
def chain(): yield from "abc" yield from "987"
輸出結(jié)果是一樣的。
yield from 的主要功能是打開(kāi)雙向通道,把最外層的調(diào)用方與最內(nèi)層的子生成器連接起來(lái),這樣,二者可以直接發(fā)送和產(chǎn)生值,甚至可以直接傳入異常。
一個(gè)復(fù)雜的例子,計(jì)算中學(xué)生的平均身高和體重:
from collections import namedtuple Result = namedtuple("Result", "count average") # 子生成器 def averager(): # <1> total = 0.0 count = 0 average = None while True: term = yield # <2> if term is None: # <3> break total += term count += 1 average = total/count return Result(count, average) # <4> # 委派生成器 def grouper(results, key): # <5> while True: # <6> results[key] = yield from averager() # <7> # 客戶(hù)端代碼,即調(diào)用端 def main(data): # <8> results = {} for key, values in data.items(): group = grouper(results, key) # <9> next(group) # <10> for value in values: group.send(value) # <11> group.send(None) # important! <12> # print(results) # uncomment to debug report(results) # 輸出報(bào)告 def report(results): for key, result in sorted(results.items()): group, unit = key.split(";") print("{:2} {:5} averaging {:.2f}{}".format( result.count, group, result.average, unit)) data = { "girls;kg": [40.9, 38.5, 44.3, 42.2, 45.2, 41.7, 44.5, 38.0, 40.6, 44.5], "girls;m": [1.6, 1.51, 1.4, 1.3, 1.41, 1.39, 1.33, 1.46, 1.45, 1.43], "boys;kg": [39.0, 40.8, 43.2, 40.8, 43.1, 38.6, 41.4, 40.6, 36.3], "boys;m": [1.38, 1.5, 1.32, 1.25, 1.37, 1.48, 1.25, 1.49, 1.46], } if __name__ == "__main__": main(data)
運(yùn)行結(jié)果:
9 boys averaging 40.42kg 9 boys averaging 1.39m 10 girls averaging 42.04kg 10 girls averaging 1.43m
委派生成器grouper()只是起到一個(gè)傳輸數(shù)據(jù)的作用,沒(méi)有進(jìn)行任何的數(shù)據(jù)處理。
生成器中都有一個(gè)無(wú)限循環(huán) while True: 這個(gè)無(wú)限循環(huán)表明,只要調(diào)用方不斷把值發(fā)送給這個(gè)協(xié)程,它就會(huì)一直接收值,然后生成結(jié)果。該循環(huán)結(jié)束條件:
調(diào)用方在協(xié)程上顯式調(diào)用 .close() 方法,
或者沒(méi)有對(duì)協(xié)程的引用,而被垃圾回收程序回收時(shí),這個(gè)協(xié)程才會(huì)終止。
終止協(xié)程的方法generator.close()
該方法致使生成器在暫停的 yield 表達(dá)式處拋出 GeneratorExit 異常。
如果生成器處理了這個(gè)異常,生成器一定不能產(chǎn)生值,否則解釋器會(huì)拋出RuntimeError異常。
如果生成器沒(méi)有處理這個(gè)異常,或者拋出StopIteration異常,即生成器已經(jīng)運(yùn)行到最后,調(diào)用方也不會(huì)報(bào)錯(cuò)。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/42346.html
摘要:進(jìn)程和線(xiàn)程究竟是什么東西傳統(tǒng)網(wǎng)絡(luò)服務(wù)模型是如何工作的協(xié)程和線(xiàn)程的關(guān)系和區(qū)別有哪些過(guò)程在什么時(shí)間發(fā)生在剛剛結(jié)束的上海站,來(lái)自七牛云存儲(chǔ)的高級(jí)工程師許智翔帶來(lái)了關(guān)于的分享中的進(jìn)程線(xiàn)程協(xié)程同步異步回調(diào)。使用紅黑樹(shù)管理就緒隊(duì)列。 進(jìn)程和線(xiàn)程究竟是什么東西?傳統(tǒng)網(wǎng)絡(luò)服務(wù)模型是如何工作的?協(xié)程和線(xiàn)程的關(guān)系和區(qū)別有哪些?IO過(guò)程在什么時(shí)間發(fā)生? 在剛剛結(jié)束的 PyCon2014 上海站,來(lái)自七牛云...
摘要:并發(fā)的方式有多種,多線(xiàn)程,多進(jìn)程,異步等。多線(xiàn)程和多進(jìn)程之間的場(chǎng)景切換和通訊代價(jià)很高,不適合密集型的場(chǎng)景關(guān)于多線(xiàn)程和多進(jìn)程的特點(diǎn)已經(jīng)超出本文討論的范疇,有興趣的同學(xué)可以自行搜索深入理解。 編程中,我們經(jīng)常會(huì)遇到并發(fā)這個(gè)概念,目的是讓軟件能充分利用硬件資源,提高性能。并發(fā)的方式有多種,多線(xiàn)程,多進(jìn)程,異步IO等。多線(xiàn)程和多進(jìn)程更多應(yīng)用于CPU密集型的場(chǎng)景,比如科學(xué)計(jì)算的時(shí)間都耗費(fèi)在CPU...
摘要:當(dāng)前狀態(tài)可以使用函數(shù)確定,該函數(shù)會(huì)返回下述字符串中的一個(gè)。解釋器正在執(zhí)行。打印消息,然后協(xié)程終止,導(dǎo)致生成器對(duì)象拋出異常。實(shí)例運(yùn)行完畢后,返回的值綁定到上。 協(xié)程 協(xié)程可以身處四個(gè)狀態(tài)中的一個(gè)。 當(dāng)前狀態(tài)可以使用inspect.getgeneratorstate(...) 函數(shù)確定,該函數(shù)會(huì)返回下述字符串中的一個(gè)。 GEN_CREATED 等待開(kāi)始執(zhí)行。 GEN_RUNNING 解...
閱讀 1971·2021-11-23 10:03
閱讀 4129·2021-11-22 09:34
閱讀 2466·2021-10-08 10:05
閱讀 2246·2019-08-30 15:53
閱讀 1686·2019-08-30 13:56
閱讀 1149·2019-08-29 16:52
閱讀 1102·2019-08-26 13:31
閱讀 3346·2019-08-26 11:45