Python 協程詳解與執行緒 程序區別

2021-09-05 19:29:18 字數 2874 閱讀 9630

在說協程前,需要先了解在python中常用迭代器和生成器,了解這兩個能夠有效的幫助你去理解協程的工作原理

概念:通過for迴圈遍歷取值的過程叫迭代

可迭代物件:可用for迴圈遍歷取值的物件,[列表、元組、字典、集合、range、字串]

判斷方式:

匯入:form collections import iterable

判斷:result =

isinstance(資料,iterable[迭代物件型別])    【返回boole值】

自定義迭代物件:

在類中定義__iter__方法建立的物件

注意:1.只要有__iter__方法的類建立的物件是可迭代物件,可迭代物件需要迭代器完成資料迭代

概念:在類裡定義__iter__和__next__方法建立的物件就是迭代器物件

優點:占用極小記憶體空間,儲存的是生成資料的方式而不是結果

實現:延遲計算 / 懶惰計算

判斷方式:

匯入:from collections import iterator

判斷:result = isinstance(資料,iterator[迭代器物件型別]) 

自定義迭代器:

iter()函式:獲取可迭代物件的迭代器,呼叫可迭代物件的__iter__方法

注意:1.迭代物件中的__iter__方法建立迭代器物件並返回

2.迭代器通過__next__獲取下乙個資料,資料取完後需要手動丟擲停止迭代的異常(raise stopiteration)

3.迴圈通過迭代器獲取資料時,需要進行異常捕獲,避免程式停止報錯

遍歷 可迭代物件

執行流程:for item in iterable

1.通過 iter() 函式獲取可迭代物件 iterable 的迭代器

2.對獲取的迭代器不斷呼叫 next() 方法獲取下乙個值並賦值給item

3.當遇到 stopiteration 的異常後迴圈結束

遍歷 迭代器

執行流程:for item in iterator

1.迴圈的迭代器不斷呼叫 next() 方法獲取下乙個值賦值給item

2.遇到stoplteration異常結束迴圈

應用場景:

迭代器的核心功能是通過next()函式呼叫返回下乙個資料值,如果資料**不是已有的集合中,而是通過程式按照一定規律生成,那麼可以不用依賴已有的資料集合,可以不用將所有要迭代的資料全部快取後依次讀取,可以節省大量的記憶體資源。

概念:不需要自己定義__iter__和__next__方法仍然可以使用next函式和for迴圈取值

場景:保證**只指定一部分就返回

建立:1.生成器表示式:將列表表示式的 [ ]更改為 ()    【生成器儲存的是演算法,占用的記憶體更少】

2.函式生成器:使用了yield關鍵字

1.在yield下可以使用return,**執行到return時,會停止迭代,丟擲停止異常

【python3才支援 return 關鍵字,可以通過except stopiteration as e: 捕獲 e.value 輸出】

兩者之間區別:

1.使用了 yield 關鍵字的函式就是生成器

2.**執行到yield會暫停掛起,將結果返回給呼叫生成器的位置,下次啟動時從掛起位置繼續

3.每次啟動生成器都會返回乙個值,yield可以返回多個值    

4.return只能返回一次值,**執行return 停止迭代

5.生成器的結束都是  stopiteration 異常丟擲,所以需要提前設定好捕獲

2.使用send方法啟動生成器傳參

異同:next是函式send是方法

next不能傳參send可以傳參

第一次呼叫必須是next,後續可以是send《傳遞的引數在yield左邊的變數獲取

send執行時也是從yield位置開始》

注意:1.單獨獲取生成器內容next(生成器物件)

2.for迴圈遍歷後,直接輸出結果,不需要next()】

概念:  微執行緒、使用者級執行緒,在def中有yield關鍵字就是協程

建立:1.greenlet

2.gevent(常用)

概述:內部封裝了greenlet,遇到io[input、output、網路、檔案操作]操作時,自動切換其他的greenlet,操作完成,再切換回來繼續執行

應用:1.匯入:from gevent import monkey

2.執行補丁:monkey.patch_all()    【使gevent識別耗時操作非同步執行處理,必須放在**開始處,避免載入問題】

3.建立協程物件:xx = gevent.spawn(方法名,位置引數(args),關鍵字引數(kwargs))

4.等待執行完成:xx.join()    【如果當前是無限迴圈且有耗時操作,可以不需要join】

5.批量程序等待:gevent.joinall([物件1],[物件2])

1.關聯

乙個程序至少有乙個執行緒,程序裡面可以有多個執行緒

乙個執行緒裡面可以 有多個協程

2.對比

1.程序是資源分配的基礎單位

2.執行緒是作業系統排程的基本單位

3.程序切換需要的資源最大,效率很低

4.執行緒切換需要的資源一般,效率一般(不基於gil的情況下)

5.執行緒切換任務資源很小,效率高

6.多程序、多執行緒根據cpu核數不一樣可能是並行,但是協程是乙個執行緒中,所以是併發

7.程序和執行緒都是由系統進行控制執行,而協程有程式設計師控制

8.程序適用於cpu密集不需要切換,大量併發計算的情況

9.多執行緒適用io密集,網路io和磁碟io

10.協程適用於:密集網路io,適合網路io

Python 程序 執行緒 協程

程序和執行緒之間的關係 執行緒是屬於程序的,執行緒執行在程序空間內,同一程序所產生的執行緒共享同一記憶體空間,當程序退出時該程序所產生的執行緒都會被強制退出並清除。執行緒可與屬於同一程序的其它執行緒共享程序所擁有的全部資源,但是其本身基本上不擁有系統資源,只擁有一點在執行中必不可少的資訊 如程式計數...

Python 程序,執行緒, 協程

程序是系統進行資源分配和排程的乙個獨立單位 最小單位 程序的幾個狀態 空 新建 建立執行乙個程式的新程序,可能的事件有 新的批處理作業 互動登入 終端使用者登入到系統 作業系統因為提供一項服務而建立 由現有的程序派生等。新建 就緒 作業系統準備好再接納乙個程序時,把乙個程序從新建態轉換為就緒態。就緒...

程序 執行緒與協程

程序的出現是為了更好的利用cpu資源使到併發成為可能。假設有兩個任務a和b,當a遇到io操作,cpu默默的等待任務a讀取完操作再去執行任務b,這樣無疑是對cpu資源的極大的浪費。聰明的老大們就在想若在任務a讀取資料時,讓任務b執行,當任務a讀取完資料後,再切換到任務a執行。注意關鍵字切換,自然是切換...