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

Python 3中的yield from語法詳解

 更新時間:2017年01月18日 11:32:06   作者:Kay Zheng  
在python 3.3里,generator新增了一個語法 yield from,這個yield from的作用是什么?語法是什么呢?下面通過這篇文章主要給大家詳細介紹了Python 3中yield from語法的相關(guān)資料,需要的朋友可以參考借鑒,下面來一起看看吧。

前言

最近在搗鼓Autobahn,它有給出個例子是基于asyncio 的,想著說放到pypy3上跑跑看竟然就……失敗了。 pip install asyncio直接報invalid syntax,粗看還以為2to3處理的時 候有問題——這不能怪我,好~多package都是用2寫了然后轉(zhuǎn)成3的——結(jié)果發(fā) 現(xiàn)asyncio本來就只支持3.3+的版本,才又回頭看代碼,赫然發(fā)現(xiàn)一句 yield from;yield我知道,但是yield from是神馬?

PEP-380

好吧這個標題是我google出來的,yield from的前世今生都在 這個PEP里面,總之大意是原本的yield語句只能將CPU控制權(quán) 還給直接調(diào)用者,當你想要將一個generator或者coroutine里帶有 yield語句的邏輯重構(gòu)到另一個generator(原文是subgenerator) 里的時候,會非常麻煩,因為外面的generator要負責為里面的 generator做消息傳遞;所以某人有個想法是讓python把消息傳遞 封裝起來,使其對程序猿透明,于是就有了yield from。

PEP-380規(guī)定了yield from的語義,或者說嵌套的generator應(yīng)該 有的行為模式。

假設(shè)A函數(shù)中有這樣一個語句

yield from B()

B()返回的是一個可迭代(iterable)的對象b,那么A()會返回一個 generator——照我們的命名規(guī)范,名字叫a——那么:

  1. b迭代產(chǎn)生的每個值都直接傳遞給a的調(diào)用者。
  2. 所有通過send方法發(fā)送到a的值都被直接傳遞給b. 如果發(fā)送的 值是None,則調(diào)用b的__next__()方法,否則調(diào)用b的send 方法。如果對b的方法調(diào)用產(chǎn)生StopIteration異常,a會繼續(xù) 執(zhí)行yield from后面的語句,而其他異常則會傳播到a中,導(dǎo) 致a在執(zhí)行yield from的時候拋出異常。
  3. 如果有除GeneratorExit以外的異常被throw到a中的話,該異常 會被直接throw到b中。如果b的throw方法拋出StopIteration, a會繼續(xù)執(zhí)行;其他異常則會導(dǎo)致a也拋出異常。
  4. 如果一個GeneratorExit異常被throw到a中,或者a的close 方法被調(diào)用了,并且b也有close方法的話,b的close方法也 會被調(diào)用。如果b的這個方法拋出了異常,則會導(dǎo)致a也拋出異常。 反之,如果b成功close掉了,a也會拋出異常,但是是特定的  GeneratorExit異常。
  5. a中yield from表達式的求值結(jié)果是b迭代結(jié)束時拋出的  StopIteration異常的第一個參數(shù)。
  6. b中的return <expr>語句實際上會拋出StopIteration(<expr>) 異常,所以b中return的值會成為a中yield from表達式的返回值。

為神馬會有這么多要求?因為generator這種東西的行為在加入throw 方法之后變得非常復(fù)雜,特別是幾個generator在一起的情況,需要 類似進程管理的元語對其進行操作。上面的所有要求都是為了統(tǒng)一 generator原本就復(fù)雜的行為,自然簡單不下來啦。

我承認我一下沒看明白PEP的作者到底想說什么,于是動手“重構(gòu)” 一遍大概會有點幫助。

一個沒用的例子

說沒用是因為你大概不會真的想把程序?qū)懗蛇@樣,但是……反正能說明 問題就夠了。

設(shè)想有這樣一個generator函數(shù):

def inner():
 coef = 1
 total = 0
 while True:
 try:
  input_val = yield total
  total = total + coef * input_val
 except SwitchSign:
  coef = -(coef)
 except BreakOut:
  return total

這個函數(shù)生成的generator將從send方法接收到的值累加到局部 變量total中,并且在收到BreakOut異常時停止迭代;至于另外 一個SwitchSign異常應(yīng)該不難理解,這里就不劇透了。

從代碼上看,由inner()函數(shù)得到的generator通過send接收用于 運算的數(shù)據(jù),同時通過throw方法接受外部代碼的控制以執(zhí)行不同 的代碼分支,目前為止都很清晰。

接下來因為需求有變動,我們需要在inner()這段代碼的前后分別加 入初始化和清理現(xiàn)場的代碼。鑒于我認為“沒壞的代碼就不要動”,我 決定讓inner()維持現(xiàn)狀,然后再寫一個outer() ,把添加的代碼放在 outer()里,并提供與inner()一樣的操作接口。由于inner()利用了 generator的若干特性,所以outer()也必須做到這五件事情:

  1. outer()必須生成一個generator;
  2. 在每一步的迭代中,outer()要幫助inner()返回迭代值;
  3. 在每一步的迭代中,outer()要幫助inner()接收外部發(fā)送的數(shù)據(jù);
  4. 在每一步的迭代中,outer()要處理inner()接收和拋出所有異常;
  5. outer()被close的時候,inner()也要被正確地close掉。

根據(jù)上面的要求,在只有yield的世界里,outer()可能是長這樣的:

def outer1():
 print("Before inner(), I do this.")
 i_gen = inner()
 input_val = None
 ret_val = i_gen.send(input_val)
 while True:
 try:
  input_val = yield ret_val
  ret_val = i_gen.send(input_val)
 except StopIteration:
  break
 except Exception as err:
  try:
  ret_val = i_gen.throw(err)
  except StopIteration:
  break
 print("After inner(), I do that.")

WTF,這段代碼比inner()本身還要長,而且還沒處理close操作。

現(xiàn)在我們來試試外星科技:

def outer2():
 print("Before inner(), I do this.")
 yield from inner()
 print("After inner(), I do that.")

除了完全符合上面的要求外,這四行代碼打印出來的時候還能省點紙。

我們可以在outer1()outer2()上分別測試 數(shù)據(jù) 以及 異常 的傳遞,不難發(fā)現(xiàn)這兩個generator的行為基本上是一致的。既然如此, 外星科技當然在大多數(shù)情況下是首選。

對generator和coroutine的疑問

從以前接觸到Python下的coroutine就覺得它怪怪的,我能看清它們的 行為模式,但是并不明白為什么要使用這種模式,generator和 coroutine具有一樣的對外接口,是generator造就了coroutine呢,還 是coroutine造就了generator?最讓我百思不得其解的是,Python下 的coroutine將“消息傳遞”和“調(diào)度”這兩種操作綁在一個yield 上——即便有了yield from,這個狀況還是沒變過——我看不出這樣做 的必要性。如果一開始就從語法層面將這兩種語義分開,并且為 generator和coroutine分別設(shè)計一套接口,coroutine的概念大概也會 容易理解一些。

總結(jié)

以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家學(xué)習(xí)或者使用python能帶來一定的幫助,如果有疑問大家可以留言交流。

相關(guān)文章

  • Django框架ORM數(shù)據(jù)庫操作實例詳解

    Django框架ORM數(shù)據(jù)庫操作實例詳解

    這篇文章主要介紹了Django框架ORM數(shù)據(jù)庫操作,結(jié)合實例形式詳細分析了Django框架ORM數(shù)據(jù)庫基本增刪改查與相關(guān)函數(shù)使用技巧,需要的朋友可以參考下
    2019-11-11
  • Django實現(xiàn)靜態(tài)文件緩存到云服務(wù)的操作方法

    Django實現(xiàn)靜態(tài)文件緩存到云服務(wù)的操作方法

    這篇文章主要介紹了Django實現(xiàn)靜態(tài)文件緩存到云服務(wù)的操作方法,本文給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-08-08
  • python requests 庫請求帶有文件參數(shù)的接口實例

    python requests 庫請求帶有文件參數(shù)的接口實例

    今天小編就為大家分享一篇python requests 庫請求帶有文件參數(shù)的接口實例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2019-01-01
  • 如何利用python實現(xiàn)windows的批處理及文件夾操作

    如何利用python實現(xiàn)windows的批處理及文件夾操作

    最近工作中需要幾個腳本運行其他程序,幾乎像一個Windows批處理文件,這篇文章主要給大家介紹了關(guān)于如何利用python實現(xiàn)windows的批處理及文件夾操作的相關(guān)資料,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下
    2022-01-01
  • NumPy迭代數(shù)組的實現(xiàn)

    NumPy迭代數(shù)組的實現(xiàn)

    本文主要介紹了NumPy迭代數(shù)組的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-02-02
  • python 循環(huán)結(jié)構(gòu)練習(xí)題

    python 循環(huán)結(jié)構(gòu)練習(xí)題

    這篇文章主要給大家分享的是python 循環(huán)結(jié)構(gòu)練習(xí)題,求兩個數(shù)最大公約數(shù)、整數(shù)反轉(zhuǎn):如12345,輸出54321等多個練習(xí)題,需要的朋友可以參考一下
    2021-11-11
  • 使用Python快速實現(xiàn)鏈接轉(zhuǎn)word文檔

    使用Python快速實現(xiàn)鏈接轉(zhuǎn)word文檔

    這篇文章主要為大家詳細介紹了如何使用Python快速實現(xiàn)鏈接轉(zhuǎn)word文檔功能,文中的示例代碼講解詳細,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2025-02-02
  • Python文件及目錄處理的方法

    Python文件及目錄處理的方法

    這篇文章主要介紹了Python文件及目錄處理的方法,Python可以用于處理文本文件和二進制文件,比如創(chuàng)建文件、讀寫文件等操作。本文介紹Python處理目錄以及文件的相關(guān)資料,需要的朋友可以參考一下
    2021-12-12
  • 學(xué)習(xí)createTrackbar的使用方法及步驟

    學(xué)習(xí)createTrackbar的使用方法及步驟

    這篇文章主要為大家介紹了學(xué)習(xí)createTrackbar的使用方法及步驟,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步
    2021-10-10
  • python中selenium操作下拉滾動條的幾種方法匯總

    python中selenium操作下拉滾動條的幾種方法匯總

    這篇文章主要介紹了python中selenium操作下拉滾動條的幾種方法匯總,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-07-07

最新評論

乐安县| 会东县| 中方县| 临洮县| 利辛县| 杨浦区| 太仆寺旗| 西丰县| 卓资县| 南京市| 甘孜| 商南县| 阳山县| 太原市| 城固县| 永丰县| 天祝| 墨竹工卡县| 南康市| 响水县| 西昌市| 梨树县| 西峡县| 丹寨县| 钟山县| 称多县| 阿城市| 祁东县| 石泉县| 丹凤县| 剑川县| 黔东| 平陆县| 富锦市| 巴林右旗| 溆浦县| 长沙县| 东山县| 阿拉善左旗| 鲁甸县| 衡阳县|