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

Python 協(xié)程與 JavaScript 協(xié)程的對比

 更新時間:2021年09月16日 11:20:32   作者:佚名  
當漸漸對 JavaScript 了解后,一查發(fā)現(xiàn) Python 和 JavaScript 的協(xié)程發(fā)展史簡直就是一毛一樣!接下來小編就大致做下橫向對比和總結,便于對這兩個語言有興趣的新人理解和吸收。

1、前言

  • 隨著 cpu 多核化,都需要實現(xiàn)由于自身歷史原因(單線程環(huán)境)下的并發(fā)功能
  • 簡化代碼,避免回調(diào)地獄,關鍵字支持
  • 有效利用操作系統(tǒng)資源和硬件:協(xié)程相比線程,占用資源更少,上下文更快

2、什么是協(xié)程?

總結一句話,協(xié)程就是滿足下面條件的函數(shù):

  •  可以暫停執(zhí)行(暫停的表達式稱為暫停點)
  •  可以從掛起點恢復(保留其原始參數(shù)和局部變量)
  •  事件循環(huán)是異步編程的底層基石

3、混亂的歷史

3.1 Python 協(xié)程的進化

  • Python2.2 中,第一次引入了生成器
  • Python2.5 中,yield 關鍵字被加入到語法中
  • Python3.4 時有了 yield fromyield from 約等于 yield + 異常處理 + send), 并試驗性引入的異步 I/O 框架 asyncio(PEP 3156)
  • Python3.5 中新增了 async/await 語法(PEP 492)
  • Python3.6 中 asyncio 庫"轉正" (之后的官方文檔就清晰了很多)

在主線發(fā)展過程中,也出現(xiàn)了很多支線的協(xié)程實現(xiàn)如 Gevent。

def foo():  
    print("foo start")  
    a = yield 1  
    print("foo a", a)  
    yield 2  
    yield 3  
    print("foo end")  
gen = foo()  
# print(gen.next())  
# gen.send("a")  
# print(gen.next())  
# print(foo().next())  
# print(foo().next())  
# 在python3.x版本中,python2.x的g.next()函數(shù)已經(jīng)更名為g.__next__(),使用next(g)也能達到相同效果。  
# next()跟send()不同的地方是,next()只能以None作為參數(shù)傳遞,而send()可以傳遞yield的值.  
print(next(gen))  
print(gen.send("a"))  
print(next(gen))  
print(next(foo()))  
print(next(foo()))  
list(foo())  
"""  
foo start  
1  
foo a a  
2  
3  
foo start  
1  
foo start  
1  
foo start  
foo a None  
foo end  
""" 

4、JavaScript 協(xié)程的進化

  • 同步代碼
  • 異步 JavaScript: callback hell
  • ES6 引入 Promise/a+, 生成器 Generators(語法 function foo(){}* 可以賦予函數(shù)執(zhí)行暫停/保存上下文/恢復執(zhí)行狀態(tài)的功能), 新關鍵詞 yield 使生成器函數(shù)暫停。
  • ES7 引入 async函數(shù)/await語法糖,async 可以聲明一個異步函數(shù)(將 Generator 函數(shù)和自動執(zhí)行器,包裝在一個函數(shù)里),此函數(shù)需要返回一個 Promise 對象。await 可以等待一個 Promise 對象 resolve,并拿到結果

Promise 中也利用了回調(diào)函數(shù)。在 then catch 方法中都傳入了一個回調(diào)函數(shù),分別在 Promise 被滿足和被拒絕時執(zhí)行,這樣就就能讓它能夠被鏈接起來完成一系列任務。

總之就是把層層嵌套的 callback 變成 .then().then()...,從而使代碼編寫和閱讀更直觀。

生成器 Generator 的底層實現(xiàn)機制是協(xié)程 Coroutine

function* foo() {  
    console.log("foo start")  
    a = yield 1;  
    console.log("foo a", a)  
    yield 2;  
    yield 3;  
    console.log("foo end")  
}  
const gen = foo();  
console.log(gen.next().value); // 1  
// gen.send("a") // http://www.voidcn.com/article/p-syzbwqht-bvv.html SpiderMonkey引擎支持 send 語法  
console.log(gen.next().value); // 2  
console.log(gen.next().value); // 3 
console.log(foo().next().value); // 1  
console.log(foo().next().value); // 1  
/*  
foo start  
1  
foo a undefined  
2  
3  
foo start  
1  
foo start  
1  
*/ 

5、Python 協(xié)程成熟體

可等待對象可以在 await 語句中使用,可等待對象有三種主要類型:協(xié)程(coroutine), 任務(task) 和 Future。

5.1 協(xié)程(coroutine)

  • 協(xié)程函數(shù):定義形式為 async def 的函數(shù);
  • 協(xié)程對象:調(diào)用 協(xié)程函數(shù) 所返回的對象
  • 舊式基于 generator(生成器)的協(xié)程

5.2 任務(Task 對象)

  • 任務 被用來“并行的”調(diào)度協(xié)程, 當一個協(xié)程通過 asyncio.create_task() 等函數(shù)被封裝為一個 任務,該協(xié)程會被自動調(diào)度執(zhí)行
  • Task 對象被用來在事件循環(huán)中運行協(xié)程。如果一個協(xié)程在等待一個 Future 對象,Task 對象會掛起該協(xié)程的執(zhí)行并等待該 Future 對象完成。當該 Future 對象 完成,被打包的協(xié)程將恢復執(zhí)行。
  • 事件循環(huán)使用協(xié)同日程調(diào)度: 一個事件循環(huán)每次運行一個 Task 對象。而一個 Task 對象會等待一個 Future 對象完成,該事件循環(huán)會運行其他 Task、回調(diào)或執(zhí)行 IO 操作。
  • asyncio.Task Future 繼承了其除 Future.set_result() Future.set_exception() 以外的所有 API。

5.3 未來對象(Future)

 Future 對象用來鏈接 底層回調(diào)式代碼 和高層異步/等待式代碼。
 不用回調(diào)方法編寫異步代碼后,為了獲取異步調(diào)用的結果,引入一個 Future 未來對象。Future 封裝了與 loop 的交互行為,add_done_callback 方法向 epoll 注冊回調(diào)函數(shù),當 result 屬性得到返回值后,會運行之前注冊的回調(diào)函數(shù),向上傳遞給 coroutine。

5.4幾種事件循環(huán)(event loop)

  • libevent/libev:Gevent(greenlet + 前期 libevent,后期 libev)使用的網(wǎng)絡庫,廣泛應用;
  •  tornado:tornado 框架自己實現(xiàn)的 IOLOOP;
  •  picoev:meinheld(greenlet+picoev)使用的網(wǎng)絡庫,小巧輕量,相較于 libevent 在數(shù)據(jù)結構和事件檢測模型上做了改進,所以速度更快。但從 github 看起來已經(jīng)年久失修,用的人不多。
  •  uvloop:Python3 時代的新起之秀。Guido 操刀打造了 asyncio 庫,asyncio 可以配置可插拔的event loop,但需要滿足相關的 API 要求,uvloop 繼承自 libuv,將一些低層的結構體和函數(shù)用 Python 對象包裝。目前 Sanic 框架基于這個庫

例子:

import asyncio  
import time  
async def exec():  
    await asyncio.sleep(2)  
    print('exec')  
# 這種會和同步效果一直  
# async def go():  
#     print(time.time())  
#     c1 = exec()  
#     c2 = exec()  
#     print(c1, c2)  
#     await c1  
#     await c2  
#     print(time.time())  
# 正確用法  
async def go():  
    print(time.time())  
    await asyncio.gather(exec(),exec()) # 加入?yún)f(xié)程組統(tǒng)一調(diào)度 
    print(time.time())  
if __name__ == "__main__":  
    asyncio.run(go()) 

6、JavaScript 協(xié)程成熟體

6.1Promise 繼續(xù)使用

Promise 本質是一個狀態(tài)機,用于表示一個異步操作的最終完成 (或失敗), 及其結果值。它有三個狀態(tài):

  •  pending: 初始狀態(tài),既不是成功,也不是失敗狀態(tài)。
  •  fulfilled: 意味著操作成功完成。
  •  rejected: 意味著操作失敗。

最終 Promise 會有兩種狀態(tài),一種成功,一種失敗,當 pending 變化的時候,Promise 對象會根據(jù)最終的狀態(tài)調(diào)用不同的處理函數(shù)。

6.2 async、await語法糖

async、await 是對 Generator Promise 組合的封裝,使原先的異步代碼在形式上更接近同步代碼的寫法,并且對錯誤處理/條件分支/異常堆棧/調(diào)試等操作更友好。

6.3 js 異步執(zhí)行的運行機制

  • 所有任務都在主線程上執(zhí)行,形成一個執(zhí)行棧。
  •  主線程之外,還存在一個"任務隊列"(task queue)。只要異步任務有了運行結果,就在"任務隊列"之中放置一個事件。
  •  一旦"執(zhí)行棧"中的所有同步任務執(zhí)行完畢,系統(tǒng)就會讀取"任務隊列"。那些對應的異步任務,結束等待狀態(tài),進入執(zhí)行棧并開始執(zhí)行。

遇到同步任務直接執(zhí)行,遇到異步任務分類為宏任務(macro-task)和微任務(micro-task)。

當前執(zhí)行棧執(zhí)行完畢時會立刻先處理所有微任務隊列中的事件,然后再去宏任務隊列中取出一個事件。同一次事件循環(huán)中,微任務永遠在宏任務之前執(zhí)行。

例子:

var sleep = function (time) {  
    console.log("sleep start")  
    return new Promise(function (resolve, reject) {  
        setTimeout(function () {  
            resolve();  
        }, time);  
    });  
};  
async function exec() {  
    await sleep(2000);  
    console.log("sleep end")  
}  
async function go() {  
    console.log(Date.now())  
    c1 = exec()  
    console.log("-------1")  
    c2 = exec()  
    console.log(c1, c2)  
    await c1;  
    console.log("-------2")  
    await c2;  
    console.log(c1, c2)  
    console.log(Date.now())  
} 
go();

6.4 event loop 將任務劃分

 主線程循環(huán)從"任務隊列"中讀取事件
 宏隊列macro task)js 同步執(zhí)行的代碼塊,setTimeoutsetInterval、XMLHttprequestsetImmediate、I/O、UI rendering等,本質是參與了事件循環(huán)的任務
微隊列(micro task)Promise、process.nextTick(node環(huán)境)、Object.observe, MutationObserver等,本質是直接在 Javascript 引擎中的執(zhí)行的沒有參與事件循環(huán)的任務
擴展閱讀 Node.js 中的 EventLoop (Javascript 運營機制詳解再淺談 Event Loop)

7、總結與對比

說明 python JavaScript 點評
進程 單進程 單進程 一致
中斷/恢復 yield,yield from,next,send yield,next 基本相同,但 JavaScript 對 send 沒啥需求
未來對象(回調(diào)包裝) Futures Promise 解決 callback,思路相同
生成器 generator Generator 將 yield 封裝為協(xié)程Coroutine,思路一樣
成熟后關鍵詞 async、await async、await 關鍵詞支持,一毛一樣
事件循環(huán) asyncio 應用的核心。事件循環(huán)會運行異步任務和回調(diào),執(zhí)行網(wǎng)絡 IO 操作,以及運行子進程。asyncio 庫支持的 API 較多,可控性高 基于瀏覽器環(huán)境基本是黑盒,外部基本無法控制,對任務有做優(yōu)先級分類,調(diào)度方式有區(qū)別 這里有很大區(qū)別,運行環(huán)境不同,對任務的調(diào)度先后不同,Python 可能和 Node.js 關于事件循環(huán)的可比性更高些,這里還需需要繼續(xù)學習

到此這篇關于Python 協(xié)程與 JavaScript 協(xié)程的對比的文章就介紹到這了,更多相關Python 協(xié)程與 JavaScript 協(xié)程內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • python數(shù)據(jù)挖掘需要學的內(nèi)容

    python數(shù)據(jù)挖掘需要學的內(nèi)容

    在本篇文章中我們給大家整理了關于python數(shù)據(jù)挖掘需要學什么的知識點指南,有興趣的朋友們跟著參考下。
    2019-06-06
  • 深入解析PYTHON?虛擬機令人拍案叫絕的字節(jié)碼設計

    深入解析PYTHON?虛擬機令人拍案叫絕的字節(jié)碼設計

    這篇文章主要為大家介紹了PYTHON虛擬機中令人拍案叫絕的字節(jié)碼設計深入詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-04-04
  • 利用python實現(xiàn)逐步回歸

    利用python實現(xiàn)逐步回歸

    今天小編就為大家分享一篇利用python實現(xiàn)逐步回歸,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-02-02
  • Python最基本的數(shù)據(jù)類型以及對元組的介紹

    Python最基本的數(shù)據(jù)類型以及對元組的介紹

    這篇文章主要介紹了Python最基本的數(shù)據(jù)類型以及對元組的介紹,來自于IBM官方網(wǎng)站技術文檔,需要的朋友可以參考下
    2015-04-04
  • django重新生成數(shù)據(jù)庫中的某張表方法

    django重新生成數(shù)據(jù)庫中的某張表方法

    今天小編就為大家分享一篇django重新生成數(shù)據(jù)庫中的某張表方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2019-08-08
  • python利用正則表達式提取字符串

    python利用正則表達式提取字符串

    相信大家在日常工作中經(jīng)常會遇見在文本中提取特定位置字符串的需求,python的正則性很好,很適合做這類字符串的提取,所以這篇文章就給大家詳細講一下提取的技巧,并通過示例代碼講解,對大家理解很有幫助,有需要的朋友們下面來一起學習學習吧。
    2016-12-12
  • pyinstaller打包可執(zhí)行文件,存放路徑包含中文無法運行的解決方案

    pyinstaller打包可執(zhí)行文件,存放路徑包含中文無法運行的解決方案

    這篇文章主要介紹了pyinstaller打包可執(zhí)行文件,存放路徑包含中文無法運行的解決方案,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-03-03
  • Python+uiautomator2實現(xiàn)手機鎖屏解鎖功能

    Python+uiautomator2實現(xiàn)手機鎖屏解鎖功能

    python-uiautomator2封裝了谷歌自帶的uiautomator2測試框架,提供便利的python接口,這篇文章給大家介紹使用Python+uiautomator2實現(xiàn)手機鎖屏解鎖(期望輸入的鎖屏密碼,基于滑動解鎖),感興趣的朋友一起看看吧
    2021-04-04
  • python tornado開啟多進程的幾種方法

    python tornado開啟多進程的幾種方法

    本文主要介紹了python tornado開啟多進程的幾種方法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2023-04-04
  • Python設計模式中的狀態(tài)模式你了解嗎

    Python設計模式中的狀態(tài)模式你了解嗎

    這篇文章主要為大家詳細介紹了Python設計模式中的狀態(tài)模式,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2022-02-02

最新評論