溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

淺析python協(xié)程相關(guān)概念

發(fā)布時(shí)間:2020-10-03 20:38:10 來源:腳本之家 閱讀:154 作者:laozhang 欄目:開發(fā)技術(shù)

這篇文章是讀者朋友的python協(xié)程的學(xué)習(xí)經(jīng)驗(yàn)之談,以下是全部?jī)?nèi)容:

協(xié)程的歷史說來話長(zhǎng),要從生成器開始講起。

如果你看過我之前的文章python奇遇記:迭代器和生成器 ,對(duì)生成器的概念應(yīng)該很了解。生成器節(jié)省內(nèi)存,用的時(shí)候才生成結(jié)果。

 

# 生成器表達(dá)式
a = (x*x for x in range(10))
# next生成值
next(a()) # 輸出0
next(a()) # 輸出1
next(a()) # 輸出4

與生成器產(chǎn)出數(shù)據(jù)不同的是,協(xié)程在產(chǎn)出數(shù)據(jù)的同時(shí)還可以接收數(shù)據(jù),具體來說就是把yield 放在了表達(dá)式的右邊。我們可以使用.send() 把數(shù)據(jù)發(fā)送給協(xié)程函數(shù)。

 def writer():
  print('-> coroutine started')
  for i in range(8):
    w = yield
    print(i+w)

w = writer()
# 本質(zhì)還是生成器
>>> w
<generator object writer at 0x000002595BC57468>
# 首先要用next()把協(xié)程激活
>>> next(w)
-> coroutine started
# 發(fā)送數(shù)據(jù)
>>> w.send(1)
1
# send到第八次之后會(huì)拋出異常
# 因?yàn)閰f(xié)程已經(jīng)結(jié)束了
---------------------------------------------------------------------------
StopIteration               Traceback (most recent call last)

第一步必須使用next() 激活協(xié)程函數(shù),這樣才能在下一步使用.send() 發(fā)送數(shù)據(jù)。

可以看到,在第8次接收完數(shù)據(jù)之后,會(huì)產(chǎn)生結(jié)束的異常,因?yàn)槌绦蛄鞒探Y(jié)束了,這是正?,F(xiàn)象。加個(gè)異常處理即可。如果需要在兩個(gè)協(xié)程間傳遞數(shù)據(jù)呢?

def writer():
  while True:
    w = yield
    print('>>', w)

def writer_wrapper(coro):
  # 激活
  next(coro)
  while True:
    # 異常處理
    try:
      x = yield
      # 發(fā)送數(shù)據(jù)給writer
      coro.send(x)
    except StopIteration:
      pass
w = writer()
wrap = writer_wrapper(w)
# 激活
next(wrap)
for i in range(4):
  wrap.send(i)
# 輸出
>> 0
>> 1
>> 2
>> 3

上面的代碼中,數(shù)據(jù)首先傳遞到writer_wrapper,之后再傳遞到writer 。

data——>writer_wrapper——>writer

可以這么寫,不過,又要預(yù)先激活,又要加異常,看起來有點(diǎn)麻煩啊。yield from 的出現(xiàn)可以解決這個(gè)問題,同樣是傳遞數(shù)據(jù):

def writer():
  while True:
    w = yield
    print('>>', w)
def writer_wrapper2(coro):
  yield from coro

一行代碼解決問題。

總之,yield from相當(dāng)于提供了一個(gè)通道,使得數(shù)據(jù)可以在協(xié)程之間流轉(zhuǎn) 。writer_wrapper2 中使用yield from coro時(shí),coro此時(shí)獲得控制權(quán),在我們.send() 數(shù)據(jù)時(shí),writer_wrapper2 被阻塞,直到writer 打印出結(jié)果。

在這個(gè)階段,協(xié)程本質(zhì)上還是由生成器構(gòu)成的。

即使我們使用yield from 簡(jiǎn)化了流程,協(xié)程和生成器的知識(shí)理解起來還是有點(diǎn)懵逼,而且yield from 用在異步編程中有諸多不順(asyncio以前就是用yield from),于是在3.5版本的python中,棄用了yield from ,新加入了兩個(gè)關(guān)鍵字async 和await ,同時(shí)協(xié)程不再是生成器類型,而是原生的協(xié)程類型。

現(xiàn)在我們定義一個(gè)協(xié)程要像下面這樣:

async def func():
  await 'some code'

不用于異步的協(xié)程該怎么用,我還不知道。所以,協(xié)程的介紹到這里就結(jié)束啦。感謝你對(duì)億速云的支持。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI