yield總結

  • 協程的優點:

協程的特點在於是一個線程執行,那和多線程比,協程有何優勢?
最大的優勢就是協程極高的執行效率。因爲子程序切換不是線程切換,而是由程序自身控制,因此,沒有線程切換的開銷,和多線程比,線程數量越多,協程的性能優勢就越明顯。

第二大優勢就是不需要多線程的鎖機制,因爲只有一個線程,也不存在同時寫變量衝突,在協程中控制共享資源不加鎖,只需要判斷狀態就好了,所以執行效率比多線程高很多。

因爲協程是一個線程執行,那怎麼利用多核CPU呢?最簡單的方法是多進程+協程,既充分利用多核,又充分發揮協程的高效率,可獲得極高的性能。

  • 從生成器到協程:

yield的本質是一個流程控制工具,可以接受數據,可以傳輸數據,使用它可以實現協作式多任務:協程可以把控制器讓步給中心調度程序,從而激活其他協程

最開始對於yield 生成器我們是使用next()一步步的運行
從一個yield處暫停然後運行到下一個yield或者運行完畢

next()讓生成器運行到下一步停止
send() 對暫停的協程發送數據
throw() 讓調用放拋出異常,在生成器中處理
close() 終止生成器

協程有四種狀態:
‘GEN_CREATED’ 已經激活等待開始執行
‘GEN_RUNNING’ 解釋器正在執行
‘GEN_SUSPENDED’ 在yield表達式處暫停
‘GEN_CLOSED’ 執行結束

def simple_coroutine():
print(“start”)
x = yield
print(“x is :”,x)

my= simple_coroutine() 創建
next(my) 此時是運行一下,也成爲預激
my.send(None) 效果相同
創 建 協 程 對 象 後 立 即 把 None 之 外 的 值 發 給 它,就會報錯

在運行當中發送這個會提前結束生成器:
coro_avg.send( None) 會傳遞StopIteration異常

generator.throw( exc_type[, exc_value[, traceback]])     致 使 生 成 器 在 暫 停 的 yield 表 達 式 處 拋 出 指 定 的 異 常。 如 果 生 成 器 處 理 了 拋 出 的 異 常, 代 碼 會 向 前 執 行 到 下 一 個 yield 表 達 式, 而 產 出 的 值 會 成 爲 調 用 generator.throw 方 法 得 到 的 返 回 值。 如 果 生 成 器 沒 有 處 理 拋 出 的 異 常, 異 常 會 向 上 冒 泡, 傳 到 調 用 方 的 上 下 文 中。

generator.close()     致 使 生 成 器 在 暫 停 的 yield 表 達 式 處 拋 出 GeneratorExit 異 常。 如 果 生 成 器 沒 有 處 理 這 個 異 常, 或 者 拋 出 了 StopIteration 異 常( 通 常 是 指 運 行 到 結 尾), 調 用 方 不 會 報 錯。 如 果 收 到 GeneratorExit 異 常, 生 成 器 一 定 不 能 產 出 值, 否 則 解 釋 器 會 拋 出 RuntimeError 異 常。 生 成 器 拋 出 的 其 他 異 常 會 向 上 冒 泡, 傳 給 調 用 方。

  • 爲什麼要用yield from,是因爲簡單

1,在獲取生成器的返回值的時候,生成器會生成StopIteration異常,而返回值(return)就在異常的value屬性裏面,由此我們取到這個值就比較麻煩
而yield from 是可以默認處理生成器生成StopIteration異常,並將值給調用方
2,yield from 有自動預激的效果,因此會不兼容自動預激的生成器

yield from X 對X對象做的第一件事情是,調用iter(X),從中獲取迭代器。
調用方 —》 委派生成器(yield from) -----》子生成器

在 生 成 器 gen 中 使 用 yield from subgen() 時, subgen 會 獲 得 控 制 權, 把 產 出 的 值 傳 給 gen 的 調 用 方, 即 調 用 方 可 以 直 接 控 制 subgen。 與 此 同 時, gen 會 阻 塞, 等 待 subgen 終 止。
簡單的來說:如果子生成器不終止,委派生成器會在yield from 表達式處永遠暫停。
一個生成器終止的辦法有:
1,出現不可處理異常
2,調用方使用close
3,生成器產生StopIteration
4,執行return語句

子生成器可以執行return語句,返回一個值,而返回的值會成爲yield from表達式的值。

高併發異步IO,就是在yield from 的基礎上,將調用方換成有個循環調度中心(event_loop,裏面實現協程的綁定,隊列),通過委託生成器管理最終的yield生成器。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章