欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Python異步編程之yield?from的用法詳解

 更新時間:2023年12月21日 10:45:44   作者:金色旭光  
yield?from?是Python3.3?后新加的語言結(jié)構(gòu),可用于簡化yield表達(dá)式的使用,這篇文章主要為大家詳細(xì)介紹了yield?from的用法,需要的可以了解一下

yield from 簡介

yield from 是Python3.3 后新加的語言結(jié)構(gòu),可用于簡化yield表達(dá)式的使用。

yield from 簡單示例:

>>> def gen():
...      yield from range(10)
...
>>> g = gen()
>>> next(g)
0
>>> next(g)
1
>>>

yield from 用于獲取生成器中的值,是對yield使用的一種優(yōu)化。

yield from 兩個最重要的特點:

1.在調(diào)用包含yield from的函數(shù)時,程序會停在yield from 這里,并將for循環(huán)的執(zhí)行傳遞到子生成器里面去。相當(dāng)于直接調(diào)用子生成器。這個功能可以稱之為傳輸通道

2.子生成器中的return,會被 res = yield from 捕獲,并賦值給res。這個可以稱之為異常處理

傳輸通道

生成器存在這樣一種調(diào)用場景,有生成器A,生成器B調(diào)用A迭代取值。main函數(shù)從迭代生成器B獲取元素。這就是所謂的嵌套生成器。如果要迭代出最內(nèi)層生成器的值,可以用如下方法:

>>> def sub_gen():
...     for i in range(5):
...         yield i
...     return 100
...
>>> def gen():
...     g = sub_gen()
...     while True:
...         try:
...             temp = next(g)
...             yield temp
...         except StopIteration as e:
...             print(f"sub_gen return {e.value}")
...             return
...
>>> g = gen()
>>> for i in g:
...     print(i)
...
0
1
2
3
4
sub_gen return 100

首先在外層生成器中使用while True 循環(huán),通過next迭代內(nèi)層生成器的值,然后捕獲異常獲取內(nèi)層生成器的返回。

使用 yield from 不需要這兩個動作就能完成同樣的功能,有效減少代碼復(fù)雜度。

>>> def sub_gen():
...     for i in range(5):
...         yield i
...     return 100
...
>>> def gen():
...     g = sub_gen()
...     res = yield from g
...     print(f"sub_gen return:{res}")
...

>>> g = gen()
>>> for i in g:
...     print(i)
...
0
1
2
3
4
sub_gen return:100

執(zhí)行流程:

當(dāng)程序執(zhí)行到 yield from 時,會暫停在這里,將for循環(huán)作用到內(nèi)層迭代器,也就是g = sub_gen()中的g變量。直到sub_gen執(zhí)行到return拋出異常被yield from捕獲,這個調(diào)用算是結(jié)束。這就是yield from的傳輸通道

注意:除了可以通過yield from 傳輸通道的能力迭代取值,也可以通過send發(fā)送值到子生成器中

異常處理

在上一篇yield使用中說明過迭代生成器時遇到return會拋出異常,獲取返回值需要捕獲異常再取值,而yield from 的功能之二就是捕獲了異常,獲取到return的值,賦值給變量。

def sub_gen():
    for i in range(5):
        yield i  
    return 100


def gen():
    g = sub_gen()
    res = yield from g
    print(f"捕獲返回值:{res}")



def main():
    g = gen()
    for i in g:
        print(i)

main()

執(zhí)行過程:

使用for循環(huán)迭代g,相當(dāng)于for循環(huán)迭代sub_gen()。

sub_gen 生成器最后的返回值作為異常拋出,調(diào)用方需要捕獲異常才能獲取返回值。但是有了yield from之后,sub_gen生成器的返回值異常就會被yield from捕獲,賦值給res變量。這就是yield from能夠處理內(nèi)層生成器的返回值。這就是yield from的異常捕獲能力

yield from 專用術(shù)語

yield from使用的專門術(shù)語:

委派生成器:包含 yield from  表達(dá)式的生成器函數(shù);即上面的gen生成器函數(shù)

子生成器:yield from 從中取值的生成器;即上面的sub_gen生成器函數(shù)

調(diào)用方:調(diào)用委派生成器的客戶端代碼;即上面的main生成器函數(shù)

三者之間的關(guān)系如下:

委派生成器在 yield from 表達(dá)式處暫停時,調(diào)用方可以直接迭代子生成器,子生成器把產(chǎn)出的值發(fā)給調(diào)用方。子生成器返回之后,解釋器會拋出StopIteration 異常,yield from會捕獲異常并取值,然后委派生成器會恢復(fù)。

yield from 實現(xiàn)的協(xié)程

在Python中有多種方式可以實現(xiàn)協(xié)程,例如:

  • greenlet 是一個第三方模塊,用于實現(xiàn)協(xié)程代碼(Gevent協(xié)程就是基于greenlet實現(xiàn))
  • yield 生成器,借助生成器的特點也可以實現(xiàn)協(xié)程代碼。
  • asyncio 在Python3.4中引入的模塊用于編寫協(xié)程代碼。
  • async & awiat 在Python3.5中引入的兩個關(guān)鍵字,結(jié)合asyncio模塊可以更方便的編寫協(xié)程代碼。

在Python3.4之前官方未提供協(xié)程的類庫,一般大家都是使用greenlet等其他來實現(xiàn)。在Python3.4發(fā)布后官方正式支持協(xié)程,即:asyncio模塊。

在Python3.4-Python3.11的代碼中可以通過asyncio + yield from的方法來實現(xiàn)原生協(xié)程。

import time
import asyncio


@asyncio.coroutine
def task1():
    print('開始運(yùn)行IO任務(wù)1...')
    yield from asyncio.sleep(2)  # 假設(shè)該任務(wù)耗時2s
    print('IO任務(wù)1已完成,耗時2s')
    return task1.__name__


@asyncio.coroutine
def task2():
    print('開始運(yùn)行IO任務(wù)2...')
    yield from asyncio.sleep(3)  # 假設(shè)該任務(wù)耗時3s
    print('IO任務(wù)2已完成,耗時3s')
    return task2.__name__


@asyncio.coroutine
def main():

    # 把所有任務(wù)添加到task中
    tasks = [task1(), task2()]

    # 子生成器
    done, pending = yield from asyncio.wait(tasks)

    # done和pending都是一個任務(wù),所以返回結(jié)果需要逐個調(diào)用result()
    for r in done:
        print(f'協(xié)程返回值:r.result()')


if __name__ == '__main__':
    start = time.time()
    # 創(chuàng)建一個事件循環(huán)對象loop
    loop = asyncio.get_event_loop()
    try:
        # 完成事件循環(huán),直到最后一個任務(wù)結(jié)束
        loop.run_until_complete(main())
    finally:
        loop.close()
    print('所有IO任務(wù)總耗時%.5f秒' % float(time.time()-start))

代碼解釋:

  • @asyncio.coroutine 裝飾的生成器函數(shù)代表著一個任務(wù)
  • yield from asyncio.sleep(3) 模擬一個IO操作,協(xié)程遇到IO會自動切換
  • loop.run_until_complete(main()) 啟動一個事件循環(huán),在循環(huán)中執(zhí)行所有任務(wù)。任務(wù)遇到IO自動切換

輸出:

/Users/yield_from_demo.py:14: DeprecationWarning: "@coroutine" decorator is deprecated since Python 3.8, use "async def" instead
  def task2():
/Users/yield_from_demo.py:22: DeprecationWarning: "@coroutine" decorator is deprecated since Python 3.8, use "async def" instead
  def main():
/Users/yield_from_demo.py:28: DeprecationWarning: The explicit passing of coroutine objects to asyncio.wait() is deprecated since Python 3.8, and scheduled for removal in Python 3.11.
  done, pending = yield from asyncio.wait(tasks)
開始運(yùn)行IO任務(wù)1...
開始運(yùn)行IO任務(wù)2...
IO任務(wù)1已完成,耗時2s
IO任務(wù)2已完成,耗時3s
協(xié)程返回值:r.result()
協(xié)程返回值:r.result()
所有IO任務(wù)總耗時3.00188秒

以上就是Python異步編程之yield from的用法詳解的詳細(xì)內(nèi)容,更多關(guān)于Python yield from的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • NumPy 數(shù)組屬性的具體使用

    NumPy 數(shù)組屬性的具體使用

    本文主要介紹了NumPy 數(shù)組屬性的具體使用,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-08-08
  • pandas數(shù)據(jù)處理之繪圖的實現(xiàn)

    pandas數(shù)據(jù)處理之繪圖的實現(xiàn)

    這篇文章主要介紹了pandas數(shù)據(jù)處理之繪圖的實現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-06-06
  • Django ORM 自定義 char 類型字段解析

    Django ORM 自定義 char 類型字段解析

    這篇文章主要介紹了Django ORM 自定義 char 類型字段解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2019-08-08
  • Python從入門到精通之環(huán)境搭建教程圖解

    Python從入門到精通之環(huán)境搭建教程圖解

    這篇文章主要介紹了Python從入門到精通之環(huán)境搭建,需要的朋友可以參考下
    2019-09-09
  • 淺析python遞歸函數(shù)和河內(nèi)塔問題

    淺析python遞歸函數(shù)和河內(nèi)塔問題

    這篇文章主要介紹了python遞歸函數(shù)和河內(nèi)塔問題,非常不錯,具有參考借鑒價值,需要的朋友可以參考下
    2017-04-04
  • 5種Python統(tǒng)計次數(shù)方法技巧

    5種Python統(tǒng)計次數(shù)方法技巧

    這篇文章主要給大家分享的是5種Python統(tǒng)計次數(shù)方法技巧,文章主要包括字典 dict 統(tǒng)計、collections.defaultdict 統(tǒng)計、List count方法、集合(set)和列表(list)統(tǒng)計、collections.Counter方法,感興趣的小伙伴一起進(jìn)入下面文章內(nèi)容吧
    2021-11-11
  • pyqt5實現(xiàn)繪制ui,列表窗口,滾動窗口顯示圖片的方法

    pyqt5實現(xiàn)繪制ui,列表窗口,滾動窗口顯示圖片的方法

    今天小編就為大家分享一篇pyqt5實現(xiàn)繪制ui,列表窗口,滾動窗口顯示圖片的方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2019-06-06
  • python argparse傳入布爾參數(shù)false不生效的解決

    python argparse傳入布爾參數(shù)false不生效的解決

    這篇文章主要介紹了python argparse傳入布爾參數(shù)false不生效的解決,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-04-04
  • Python+OpenCV進(jìn)行人臉面部表情識別

    Python+OpenCV進(jìn)行人臉面部表情識別

    這篇文章主要介紹了通過Python OpenCV實現(xiàn)對人臉面部表情識別,判斷人是否為笑臉,文中的示例代碼非常詳細(xì),需要的朋友可以參考一下
    2021-12-12
  • Python for i in range ()用法詳解

    Python for i in range ()用法詳解

    今天小編就為大家分享一篇Python for i in range ()用法詳解,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2019-12-12

最新評論