最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

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

 更新時(shí)間: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 兩個(gè)最重要的特點(diǎn):

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

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

傳輸通道

生成器存在這樣一種調(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 不需要這兩個(gè)動(dòng)作就能完成同樣的功能,有效減少代碼復(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 時(shí),會(huì)暫停在這里,將for循環(huán)作用到內(nèi)層迭代器,也就是g = sub_gen()中的g變量。直到sub_gen執(zhí)行到return拋出異常被yield from捕獲,這個(gè)調(diào)用算是結(jié)束。這就是yield from的傳輸通道

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

異常處理

在上一篇yield使用中說明過迭代生成器時(shí)遇到return會(huì)拋出異常,獲取返回值需要捕獲異常再取值,而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生成器的返回值異常就會(huì)被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á)式處暫停時(shí),調(diào)用方可以直接迭代子生成器,子生成器把產(chǎn)出的值發(fā)給調(diào)用方。子生成器返回之后,解釋器會(huì)拋出StopIteration 異常,yield from會(huì)捕獲異常并取值,然后委派生成器會(huì)恢復(fù)。

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

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

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

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

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

import time
import asyncio


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


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


@asyncio.coroutine
def main():

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

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

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


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

代碼解釋:

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

輸出:

/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已完成,耗時(shí)2s
IO任務(wù)2已完成,耗時(shí)3s
協(xié)程返回值:r.result()
協(xié)程返回值:r.result()
所有IO任務(wù)總耗時(shí)3.00188秒

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

相關(guān)文章

  • numpy工程實(shí)踐之np.savetxt()存儲(chǔ)數(shù)據(jù)

    numpy工程實(shí)踐之np.savetxt()存儲(chǔ)數(shù)據(jù)

    NumPy提供了多種存取數(shù)組內(nèi)容的文件操作函數(shù),保存數(shù)組數(shù)據(jù)的文件可以是二進(jìn)制格式或者文本格式,下面這篇文章主要給大家介紹了關(guān)于numpy工程實(shí)踐之np.savetxt()存儲(chǔ)數(shù)據(jù)的相關(guān)資料,需要的朋友可以參考下
    2023-05-05
  • Tensorflow加載預(yù)訓(xùn)練模型和保存模型的實(shí)例

    Tensorflow加載預(yù)訓(xùn)練模型和保存模型的實(shí)例

    今天小編就為大家分享一篇Tensorflow加載預(yù)訓(xùn)練模型和保存模型的實(shí)例,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-07-07
  • 詳解Python安裝tesserocr遇到的各種問題及解決辦法

    詳解Python安裝tesserocr遇到的各種問題及解決辦法

    這篇文章主要介紹了詳解Python安裝tesserocr遇到的各種問題及解決辦法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-03-03
  • python對Excel按條件進(jìn)行內(nèi)容補(bǔ)充(推薦)

    python對Excel按條件進(jìn)行內(nèi)容補(bǔ)充(推薦)

    這篇文章主要介紹了python對Excel按條件進(jìn)行內(nèi)容補(bǔ)充的相關(guān)知識,非常不錯(cuò),本文通過實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2019-11-11
  • 簡單講解Python編程中namedtuple類的用法

    簡單講解Python編程中namedtuple類的用法

    namedtuple類位域Collections模塊中,有了namedtuple后通過屬性訪問數(shù)據(jù)能夠讓我們的代碼更加的直觀更好維護(hù),下面就來簡單講解Python編程中namedtuple類的用法
    2016-06-06
  • django 通過ajax完成郵箱用戶注冊、激活賬號的方法

    django 通過ajax完成郵箱用戶注冊、激活賬號的方法

    本篇文章主要介紹了django 通過ajax完成郵箱用戶注冊、激活賬號的方法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2018-04-04
  • python更新列表的方法

    python更新列表的方法

    這篇文章主要介紹了python更新列表的方法,實(shí)例分析了Python列表賦值的相關(guān)技巧,需要的朋友可以參考下
    2015-07-07
  • python實(shí)現(xiàn)人機(jī)對戰(zhàn)的五子棋游戲

    python實(shí)現(xiàn)人機(jī)對戰(zhàn)的五子棋游戲

    這篇文章主要為大家詳細(xì)介紹了python實(shí)現(xiàn)人機(jī)對戰(zhàn)的五子棋游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-04-04
  • Python處理mysql特殊字符的問題

    Python處理mysql特殊字符的問題

    今天小編就為大家分享一篇Python處理mysql特殊字符的問題,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-03-03
  • 利用PyQt5制作一個(gè)豆瓣電影信息查看器

    利用PyQt5制作一個(gè)豆瓣電影信息查看器

    這篇文章主要介紹了如何通過PyQt5制作一個(gè)查看器,可以查看豆瓣前100名電影的信息,當(dāng)然這個(gè)爬取信息比較簡單。感興趣的小伙伴可以試一試
    2022-01-01

最新評論

洛宁县| 万安县| 安国市| 常德市| 于都县| 佛学| 江华| 麻城市| 阿瓦提县| 宁陕县| 抚宁县| 砀山县| 墨脱县| 乐安县| 遂平县| 康保县| 图片| 瓦房店市| 财经| 宁南县| 普定县| 威远县| 江达县| 南丰县| 高要市| 洪泽县| 九江县| 青州市| 佛坪县| 二连浩特市| 公主岭市| 金堂县| 哈尔滨市| 梁山县| 博湖县| 梅州市| 玉山县| 贺兰县| 开平市| 许昌市| 梅河口市|