日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > python >内容正文

python

python基础 协程

發(fā)布時(shí)間:2024/4/15 python 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 python基础 协程 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

說到并發(fā)編程,大家容易想到的就是:進(jìn)程、線程、協(xié)程、異步IO。四者在實(shí)現(xiàn)上卻有共通之處,不外乎調(diào)度二字。

進(jìn)程:操作系統(tǒng)進(jìn)程系統(tǒng)調(diào)度,調(diào)度號(hào):pid,基本由操作系統(tǒng)提供調(diào)度支持

線程:操作系統(tǒng)線程調(diào)度,調(diào)度號(hào):TCB,虛擬機(jī)提供一部分支持

協(xié)程:程序自己進(jìn)行調(diào)度,調(diào)度號(hào):函數(shù)名,全部由程序自身完成。

異步IO:由消息中間件負(fù)責(zé)調(diào)度,調(diào)度號(hào):消息隊(duì)列。

進(jìn)程、線程、協(xié)程它們?nèi)齻€(gè)實(shí)現(xiàn)的是時(shí)間復(fù)用,達(dá)到邏輯上的同步;而異步IO則僅僅實(shí)現(xiàn)了應(yīng)用的解耦合,必須要配合前面三者中的一個(gè)或多個(gè)來實(shí)現(xiàn)并發(fā)的處理;

下面專門講協(xié)程

協(xié)程,顧名思義就是協(xié)同合作的程序,一個(gè)程序里可以有很多協(xié)程,這些協(xié)程在主線程的調(diào)度下,表現(xiàn)得像是并發(fā)執(zhí)行得一樣;這樣得好處就是:輕量級(jí)。

人們常說:線程是輕量級(jí)的進(jìn)程;到了協(xié)程這里,我們可以說協(xié)程是最輕量級(jí)的執(zhí)行單元;不會(huì)再有比協(xié)程更輕的了;一個(gè)協(xié)程可以是一個(gè)函數(shù)或者任何可調(diào)用對(duì)象,它的調(diào)度也完全由程序自身控制,因此可以將其調(diào)度開銷按照自身需要降到最低。這就是它的優(yōu)勢(shì)所在。

yield 關(guān)鍵字

def func_1():
while True:
x = yield
print("value:", x)


if __name__ == '__main__':
g = func_1()
print('啟動(dòng)生成器并接收返回值:', next(g))
print('啟動(dòng)生成器并接收返回值:', g.send(1))
print('啟動(dòng)生成器并接收返回值:', g.send(2))
print('啟動(dòng)生成器并接收返回值:', next(g))

'''
啟動(dòng)生成器并接收返回值: None
value: 1
啟動(dòng)生成器并接收返回值: None
value: 2
啟動(dòng)生成器并接收返回值: None
value: None
啟動(dòng)生成器并接收返回值: None
'''
def func_2():
while True:
x = yield 8888
print("value:", x)


if __name__ == '__main__':
g = func_2()
print('啟動(dòng)生成器并接收返回值:', next(g))
print('啟動(dòng)生成器并接收返回值:', g.send(1))
print('啟動(dòng)生成器并接收返回值:', g.send(2))
print('啟動(dòng)生成器并接收返回值:', next(g))

'''
啟動(dòng)生成器并接收返回值: 8888
value: 1
啟動(dòng)生成器并接收返回值: 8888
value: 2
啟動(dòng)生成器并接收返回值: 8888
value: None
啟動(dòng)生成器并接收返回值: 8888
'''

?

首先,如果你還沒有對(duì)yield有個(gè)初步分認(rèn)識(shí),那么你先把yield看做“return”,這個(gè)是直觀的,它首先是個(gè)return,普通的return是什么意思,就是在程序中返回某個(gè)值,返回之后程序就不再往下運(yùn)行了。看做return之后再把它看做一個(gè)是生成器(generator)的一部分(帶yield的函數(shù)才是真正的迭代器),好了,如果你對(duì)這些不明白的話,那先把yield看做return,然后直接看下面的程序,你就會(huì)明白yield的全部意思了:

def func():print("in func, generator starting...")while True:res = yield 100print("res>>>>>>>:", res)if __name__ == '__main__':g = func()print('啟動(dòng)生成器并接收返回值', next(g))print("***************************")print('再次啟動(dòng)生成器并接收返回值', next(g))''' in func, generator starting... 啟動(dòng)生成器并接收返回值 100 *************************** res>>>>>>>: None 再次啟動(dòng)生成器并接收返回值 100 ''' View Code

代碼運(yùn)行順序解釋:

>>>func(),程序開始執(zhí)行以后,由于func函數(shù)中含有yield關(guān)鍵字,所以func函數(shù)不會(huì)真正執(zhí)行,而是得到一個(gè)生成器(相當(dāng)于一個(gè)對(duì)象)

>>>g = func(),通過func()得到一個(gè)生成器對(duì)象后,賦值給g

>>>next(g),啟動(dòng)生成器,進(jìn)入func函數(shù),打印‘in func,generator starting...’,進(jìn)入循環(huán),在yield 100處暫停,相當(dāng)于return 100

>>>print('啟動(dòng)生成器并接收返回值', next(g)),接收yield(return)的值,此處是yield 100,所以屏幕上打印===啟動(dòng)生成器并接收返回值 100===

>>>print("***************************"),在屏幕上打印分割線

>>>next(g),程序在上次暫停位置重新啟動(dòng)并執(zhí)行賦值操作

? ? ? ? ? ? ? ? ? ? ?yield=None,所以res=yield,相當(dāng)于res=None
? ? ? ? ? ? ? ? ? ? ?print("res>>>>>>>:", res)在屏幕上打印res>>>>>>>: None
? ? ? ? ? ? ? ? ? ? ?然后繼續(xù)循環(huán),在yield 100處再次暫停,相當(dāng)于return 100

>>>print('再次啟動(dòng)生成器并接收返回值', next(g)),接收yield(return)的值,此處是yield 100,所以屏幕上打印===再次啟動(dòng)生成器并接收返回值 100===

?

到這里你可能就明白yield和return的關(guān)系和區(qū)別了,帶yield的函數(shù)是一個(gè)生成器,而不是一個(gè)函數(shù)了,這個(gè)生成器有一個(gè)函數(shù)就是next函數(shù),next就相當(dāng)于“下一步”生成哪個(gè)數(shù),這一次的next開始的地方是接著上一次的next停止的地方執(zhí)行的,所以調(diào)用next的時(shí)候,生成器并不會(huì)從func函數(shù)的開始執(zhí)行,只是接著上一步停止的地方開始,然后遇到y(tǒng)ield后,return出要生成的數(shù),此步就結(jié)束。

def func():print("in func, generator starting...")while True:res = yield 100print("res>>>>>>>:", res)if __name__ == '__main__':g = func()print('啟動(dòng)生成器并接收返回值', next(g))print("***************************")print('next再次啟動(dòng)生成器并接收返回值', next(g))print("***************************")print('send再次啟動(dòng)生成器并接收返回值', g.send(888))''' in func, generator starting... 啟動(dòng)生成器并接收返回值 100 *************************** res>>>>>>>: None next再次啟動(dòng)生成器并接收返回值 100 *************************** res>>>>>>>: 888 send再次啟動(dòng)生成器并接收返回值 100 ''' View Code

代碼運(yùn)行順序解釋:

......

>>>print("***************************"),在屏幕上打印分割線

>>>g.send(888),程序在上次暫停位置重新啟動(dòng)并執(zhí)行賦值操作

? ? ? ? ? ? ? ? ? ? ? ? ? ? ?g.send(888),相當(dāng)于yield=888,所以res=yield,相當(dāng)于res=888,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ?print("res>>>>>>>:", res)在屏幕上打印res>>>>>>>: 888,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ?然后繼續(xù)循環(huán),在yield 100處再次暫停,相當(dāng)于return 100。

>>>print('send再次啟動(dòng)生成器并接收返回值', g.send(888)),接收yield(return)的值,此處是yield 100,所以屏幕上打印===send再次啟動(dòng)生成器并接收返回值 100===

?

send函數(shù)的概念:上面那個(gè)res的值為什么是None,這個(gè)變成了888,到底為什么,這是因?yàn)?#xff0c;send是發(fā)送一個(gè)參數(shù)給res的,因?yàn)樯厦嬷v到,return的時(shí)候,并沒有把100賦值給res,下次執(zhí)行的時(shí)候只好繼續(xù)執(zhí)行賦值操作,只好賦值為None了,而如果用send的話,開始執(zhí)行的時(shí)候,先接著上一次(return 100之后)執(zhí)行,先把888賦值給了res,然后執(zhí)行next的作用,遇見下一回的yield,return出結(jié)果后結(jié)束

?

轉(zhuǎn)載于:https://www.cnblogs.com/sniperths/p/10512654.html

總結(jié)

以上是生活随笔為你收集整理的python基础 协程的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。