【python】生成器

生成器

直接總結

  1. 創建生成器的方法
    1. 生成器表達式:(i for i in [1, 2])
    2. yield: 函數中出現yield這個函數就是生成器,函數(生成器)執行到yield時會返回yield后面的值,并暫停,知道下次被喚醒后會從暫停處接著執行
  2. 迭代生成器: 生成器實現了python迭代協議,可以使用next()for迭代
  3. 向生成器發送消息:如果yield出現在表達式右邊,下一次生成器被send()喚醒時,上一個yield會接收send()發過來的消息賦值給上一個yield左邊的變量。
  4. 喚醒生成器:
    1. next():喚醒生成器,讓他運行到下一個yield處,返回yield出來的值
    2. send():喚醒生成器,并給生成器發送一個消息,同時讓他運行到下一個yield處,返回yield出來的值,不能直接一開始就發送具體的數據
  5. 停止生成器:close()
  6. 發送異常:throw(type, val)
  7. yield from

創建與使用生成器

直接使用生成器表達式就可以快速創建一個生成器

gen = (i for i in range(10))
print(type(gen))
for i in gen:print(i, end=" ")# <class 'generator'>
# 0 1 2 3 4 5 6 7 8 9 

生成器實現了__next__可以使用next()來獲取下一個值,當然也可以使用for循環遍歷

更加常見的創建生成器的方式是使用yield關鍵字,一個函數如果出現yield關鍵字這個函數就會變成生成器,當函數運行到yield時會暫停下來,”返回“一個結果,下一次喚醒生成器時,函數會從停下來的地方繼續運行

def builder_demo():yield 0yield 1return 3if __name__ == '__main__':bd = builder_demo()print(type(bd))print(next(bd))print(next(bd))print(next(bd))print(next(bd))
<class 'generator'>
0
1
Traceback (most recent call last):File "E:/python/coroutine_test.py", line 12, in <module>print(next(bd))
StopIteration: 3

當沒有下一個元素時調用next會拋出StopIteration異常,return的值會作為異常的值

if __name__ == '__main__':bd = builder_demo()while True:try:print(next(bd))except StopIteration as e:print(f'result is {e.value}')break
0
1
result is 3

yield不但可以“傳遞出值”,也可以接收值

def builder_demo():news = yield 0print(f'news:  {news}')news1 = yield 1print(f'new1: {news1}')return 3if __name__ == '__main__':bd = builder_demo()print(next(bd))result1 = bd.send("hello")print(result1)result2 = bd.send("hello2")print(result2)
0
news:  hello
1
new1: hello2
Traceback (most recent call last):File "E:python/coroutine_test.py", line 14, in <module>result2 = bd.send("hello2")
StopIteration: 3

往暫停處傳遞消息使用生成器的send()方法,這個方法還可以自動迭代到生成器中的下一個對象(有next())的作用。

生成器是先yield出數據,等到下一次生成器被喚醒時,才會接收send()的數據,然后再yield出下一個數據,所以不能一開始就直接調用send()發送具體的值,會拋出TypeError

TypeError: can't send non-None value to a just-started generator

應該先執行一次next()或執行一次generator.send(None),讓生成器yield出數據,send(None)的作用與next()基本一樣

生成器也可以停止,使用close()方法

def builder_demo():news = yield 0print(f'news:  {news}')news1 = yield 1print(f'new1: {news1}')yield 4yield 5return 3if __name__ == '__main__':bd = builder_demo()# print(next(bd))print(bd.send(None))result1 = bd.send("hello")print(result1)result2 = bd.send("hello2")print(result2)bd.close()print(next(bd))
0
news:  hello
1
new1: hello2
4
Traceback (most recent call last):File "E:python/coroutine_test.py", line 20, in <module>print(next(bd))
StopIteration

close()之后再使用next(),會拋出StopIteration異常

除此之外,還可以向生成器發送異常

if __name__ == '__main__':bd = builder_demo()print(bd.send(None))bd.throw(Exception, TypeError("throw new error"))print(next(bd))
0
Traceback (most recent call last):File "E:python/coroutine_test.py", line 19, in <module>bd.throw(Exception, TypeError("throw new error"))File "E:python/coroutine_test.py", line 2, in builder_demonews = yield 0
TypeError: throw new error

yield from

yield from 是python3.3 PEP380 新添加的特性,它允許將一個生成器的部分操作委派給另一個生成器,除了向子生成器委派任務,yield from也可以直接作用于迭代器,將迭代器中的每個對象逐一yield出來,如:

def demo(*args, **kwargs):for i in args:for j in i:yield j
# 等價于
def demo(*args, **kwargs):for i in args:yield from i

上面的函數其實就是itertools.chain() 作用是將多個迭代器中的元素迭代出來

生成器嵌套

1、調用方:調用委派生成器的客戶端(調用方)代碼
2、委托生成器:包含yield from表達式的生成器函數
3、子生成器:yield from后面加的生成器函數

yield from 可以架設一個調用方子生成器之間的雙向橋梁

final_result = {}def calculate():total = 0nums = []while True:info = yieldif not info:breaktotal += infonums.append(info)# return 的值會被賦值給yield from 左邊的變量return total, numsdef middle(key: str, gen):while True:final_result[key] = yield from gen()print(final_result)def main():data = {"apple": [230, 569, 234, 776],"banana": [564, 213, 798, 327],"strawberry": [98, 76, 120, 436, 55],"orange": [78, 67, 345, 124]}for key, value in data.items():# 不要傳遞calculate()!mid = middle(key, calculate)mid.send(None)  # 初激for v in value:mid.send(v)mid.send(None)if __name__ == '__main__':main()

為什么“多此一舉”架設一個“橋梁”?

  • yield from 在內部處理了大量可能的異常,簡化開發,提高代碼安全性和可讀性

生成器的作用

  1. 適用于對大量數據的處理:如果要對產生的大量數據進一步處理時,使用容器就只能先得到所有要處理的數據,存到容器,再逐個對容器中的數據遍歷,再加工,最后得到目標數據,這樣第一步產生的“中間數據”只用一次,但仍需大量空間儲存;使用生成器可以產生一個,加工一個,節約內存,提高效率
  2. 用于協程

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/457485.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/457485.shtml
英文地址,請注明出處:http://en.pswp.cn/news/457485.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

python redis 性能測試臺_Redis性能測試

Redis 性能測試Redis 性能測試是通過同時執行多個命令實現的。Redis性能測試主要是通過src文件夾下的redis-benchmark來實現(Linux系統下)語法redis 性能測試的基本命令如下&#xff1a;redis-benchmark [option] [option value]實例以下實例同時執行 10000 個請求來檢測性能&a…

Java IO 系統

Java IO系統 File類 用來處理文件目錄&#xff0c;既可以代表一個特定文件的名稱&#xff0c;也可以代表一組文件的名稱&#xff0c;如果代表的是一個文件組&#xff0c;可以調用File.list()方法返回一個字符數組。 list()不傳遞任何參數時返回該目錄下所有文件或文件名的字…

Linux Crontab 任務管理工具命令以及示例

Crontab 是 Linux 平臺下的一款用于循環執行例行任務的工具,Linux 系統由 cron (crond) 這個系統服務來控制任務 , Linux系統本來就有很多的計劃任務需要啟動 , 所以這個系統服務是默認開機啟動的 。 Linux 為使用者提供的計劃任務的命令就是 Crontab Crontab 是 Linux 下用來周…

Linux 網絡編程詳解一(IP套接字結構體、網絡字節序,地址轉換函數)

IPv4套接字地址結構 struct sockaddr_in {uint8_t sinlen;&#xff08;4個字節&#xff09;sa_family_t sin_family;&#xff08;4個字節&#xff09;in_port_t sin_port;&#xff08;2個字節&#xff09;struct in_addr sin_addr;&#xff08;4個字節&#xff09;char sin_zer…

地籍cad的lisp程序大集合_AutoCAD-LISP程序100例

{:soso_e179:}AutoCAD-LISP程序100例.JPG (143.82 KB, 下載次數: 28)2011-10-18 14:42 上傳有說明很好&#xff01;頂如果您使用 AutoCAD,下面的內容對您一定有幫助。在某些方面能大大提高您的工作效率。下面的程序均以源程序方式給出&#xff0c;您可以使用、參考、修改它。bg…

javascript中數組的22種方法

前面的話數組總共有22種方法&#xff0c;本文將其分為對象繼承方法、數組轉換方法、棧和隊列方法、數組排序方法、數組拼接方法、創建子數組方法、數組刪改方法、數組位置方法、數組歸并方法和數組迭代方法共10類來進行詳細介紹對象繼承方法數組是一種特殊的對象&#xff0c;繼…

javascript/jquery高度寬度詳情解說分析

為什么80%的碼農都做不了架構師&#xff1f;>>> 一、window對象表示瀏覽器中打開的窗口 二、window對象可以省略 一、document對象是window對象的一部分 二、瀏覽器的HTML文檔成為Document對象 window.location和document.location window對象的location屬性引用的…

農用地包括哪些地類_土地地類一覽表

一級類二級類三級類含義編號三大類名稱編號名稱編號名稱1農用地指直接用于農業生產的土地&#xff0c;包括耕地&#xff0c;園地&#xff0c;林地&#xff0c;牧草地及其他的農業用地11耕地指種植農作物、土地&#xff0c;包括熟地、新開發復墾整理地&#xff0c;休閑地、輪歇地…

紅黑樹插入時的自平衡

紅黑樹插入時的自平衡 紅黑樹實質上是一棵自平衡的二叉查找樹&#xff0c;引入帶顏色的節點也是為了方便在進行插入或刪除操作時&#xff0c;如果破壞了二叉查找樹的平衡性能通過一系列變換保持平衡。 紅黑樹的性質 每個節點要么是紅色&#xff0c;要么是黑色根節點必須是黑…

說一下自己對于 Linux 哲學的理解

查閱了一些資料&#xff0c;官方的哲學思想貌似是&#xff1a; 一切皆文件由眾多單一目的的小程序&#xff0c;一個程序只實現一個功能&#xff0c;多個程序組合完成復雜任務文本文件保存配置信息盡量避免與用戶交互什么&#xff0c;你問我的理解&#xff1f;哲學思想&#xff…

UWP學習記錄

微軟{X:Bind}、{Binding}資料網站 &#xff1a; https://msdn.microsoft.com/windows/uwp/xaml-platform/x-bind-markup-extension在View的ItemTemplate中綁定ViewModel的方法&#xff1a;1 <ItemsControl Name"XX" ItemsSource"{x:Bind VM.XXModels,ModeOne…

dw1000信標碼_DW1000方案工牌型UWB標簽,助力10厘米高精度室內定位!

DW1000方案工牌型UWB標簽&#xff0c;助力10厘米高精度室內定位&#xff01;發布日期&#xff1a;2019-04-01 瀏覽次數&#xff1a;244次微能信息(95power)推出一款工牌型UWB標簽VDU1510 &#xff0c;廣泛應用于超寬帶UWB定位系統&#xff0c;最高可實現10cm高精度人員定位。工…

【Java】HashMap源碼(1.7)

Life is not a ridiculous number of life, the meaning of life lies in life itself HashMap源碼 散列集 數組和鏈表可以保持元素插入的順序&#xff0c;對數組來說&#xff0c;他的優點是擁有連續的存儲空間&#xff0c;因此可以使用元素下標快速訪問&#xff0c;但缺點在…

Docker 基本用法

1.安裝&#xff1a; wget http://mirrors.yun-idc.com/epel/6/i386/epel-release-6-8.noarch.rpm rpm -ivh epel-release-6-8.noarch.rpm yum install docker-io -y2.獲取鏡像 pull docker pull ubuntu docker pull ubuntu:14.043.運行這個鏡像&#xff0c;在其中運行bash應用…

畫刷的使用

1.畫刷的定義&#xff1a; HBRUSH hBrush; windows 自定義的畫刷&#xff1a; WHITE_BRUSH、LTGRAY_BRUSH、GRAY_BRUSH、DKGRAY_BRUSH、BLACK_BRUSH和NULL_BRUSH &#xff08;也叫HOLLOW_BRUSH&#xff09; 獲取方法如下&#xff1a; hBrush (HBRUSH) GetStockObject (GRAY_BR…

dataframe 控對象_iOS知識 - 常用小技巧大雜燴

1&#xff0c;打印View所有子視圖po [[self view]recursiveDescription]2&#xff0c;layoutSubviews調用的調用時機* 當視圖第一次顯示的時候會被調用。* 添加子視圖也會調用這個方法。* 當本視圖的大小發生改變的時候是會調用的。* 當子視圖的frame發生改變的時候是會調用的。…

【Java】jdk 1.8 新特性——Lambda表達式

Lambda表達式 jdk 1.8 新加入的特性&#xff0c;簡化了簡單接口的實現 函數式接口 函數式中只有一個待實現的方法&#xff0c;可以使用FunctionalInterface注解標注函數式接口.這個接口中只能有一個待實現的方法&#xff0c;但可以包含默認方法&#xff0c;靜態方法以及Obje…

【Todo】Java8新特性學習

參考這篇文章吧&#xff1a; http://blog.csdn.net/vchen_hao/article/details/53301073 還有一個系列轉載于:https://www.cnblogs.com/charlesblc/p/6123380.html

jsp調整字體大小font_html font標簽如何設置字體大小?

首先我們先來看看htmlfont標簽是如何來設置字體大小的&#xff1a;都只到htmlfont標簽是個專門用來設置字體的標簽&#xff0c;雖然在html5中用的會很少(因為都用css樣式來設置font標簽里面的屬性)&#xff0c;但是個人覺得font標簽還是相當強大的標簽的&#xff0c;為什么這么…

runtime官方文檔

OC是一種面向對象的動態語言&#xff0c;作為初學者可能大多數人對面向對象這個概念理解的比較深&#xff0c;而對OC是動態語言這一特性了解的比較少。那么什么是動態語言&#xff1f;動態語言就是在運行時來執行靜態語言的編譯鏈接的工作。這就要求除了編譯器之外還要有一種運…