python生成器
1. 什么是生成器?
生成器(英文名 Generator ),是一個(gè)可以像迭代器那樣使用for循環(huán)來(lái)獲取元素的函數(shù)。
生成器的出現(xiàn)(Python 2.2 +),實(shí)現(xiàn)了延時(shí)計(jì)算,從而緩解了在大量數(shù)據(jù)下內(nèi)存消耗過(guò)猛的問(wèn)題。
當(dāng)你在 Python Shell 中敲入一個(gè)生成器對(duì)象,會(huì)直接輸出 generator object
提示你這是一個(gè)生成器對(duì)象
>>> gen = (i for i in range(5))
>>> gen
at 0x10cae50b0>
2. 如何創(chuàng)建生成器?
使用列表推導(dǎo)式
在上面已經(jīng)演示過(guò),正常我們使用列表推導(dǎo)式時(shí)是下面這樣子,使用 []
,此時(shí)生成的是列表。
>>> mylist = [i for i in range(5)]
>>> mylist
[0, 1, 2, 3, 4]
而當(dāng)你把 []
換成 ()
,返回的就不是列表了,而是一個(gè)生成器
>>> gen = (i for i in range(5))
>>> gen
at 0x10cae50b0>
使用 yield
yield
是什么東西呢? 它相當(dāng)于我們函數(shù)里的 return,但與 return 又有所不同。
當(dāng)一個(gè)函數(shù)運(yùn)行到 yield 后,函數(shù)的運(yùn)行會(huì)暫停,并且會(huì)把 yield 后的值返回出去。
若 yield 沒(méi)有接任何值,則返回 None
yield 雖然返回了,但是函數(shù)并沒(méi)有結(jié)束
請(qǐng)看如下代碼,我定義了一個(gè) generator_factory
函數(shù),當(dāng)我執(zhí)行 gen = generator_factory()
時(shí),gen 就是一個(gè)生成器對(duì)象
>>> def generator_factory(top=5):
... index = 0
... while index < top:
... print("index 值為: " + str(index))
... index = index + 1
... yield index
... raise StopIteration
...
>>> gen = generator_factory()
>>> gen
3. 生成器的使用
從一個(gè)生成器對(duì)象中取出元素,和我們前面學(xué)過(guò)的通過(guò)切片訪問(wèn)列表中的元素不一樣,它沒(méi)有那么直觀。
想要從生成器對(duì)象中取出元素,只有兩種方法:
第一種方法:使用 next 方法一個(gè)一個(gè)地把元素取出來(lái),如果元素全部取完了,生成器會(huì)拋出 StopIteration
的異常。
>>> gen = (x for x in range(3))
>>> gen
at 0x1072400b0>
>>> next(gen)
0
>>> next(gen)
1
>>> next(gen)
2
>>> next(gen)
Traceback (most recent call last):
File "", line 1, in
StopIteration
第二種方法:使用 for 循環(huán)一個(gè)一個(gè)地迭代出來(lái)
>>> gen = (x for x in range(3))
>>> for i in gen:
... print(i)
...
0
1
2
4. 生成器的激活
生成器對(duì)象,在創(chuàng)建后,并不會(huì)執(zhí)行任何的代碼邏輯。
想要從生成器對(duì)象中獲取元素,那么第一步要觸發(fā)其運(yùn)行,在這里稱之為激活。
方法有兩種:
使用next()
:上面已經(jīng)講過(guò)
使用generator.send(None)
還以下面這段代碼為例,可以看到 gen.send(None)
相當(dāng)于執(zhí)行了 next(gen)
>>> def generator_factory(top=5):
... index = 0
... while index < top:
... print("index 值為: " + str(index))
... index = index + 1
... yield index
... raise StopIteration
...
>>>
>>> gen = generator_factory()
>>> gen.send(None)
index 值為: 0
1
>>> gen.send(None)
index 值為: 1
2
5. 生成器的狀態(tài)
生成器在其生命周期中,會(huì)有如下四個(gè)狀態(tài)
GEN_CREATED
# 生成器已創(chuàng)建,還未被激活
GEN_RUNNING
# 解釋器正在執(zhí)行(只有在多線程應(yīng)用中才能看到這個(gè)狀態(tài))
GEN_SUSPENDED
# 在 yield 表達(dá)式處暫停
GEN_CLOSED
# 生成器執(zhí)行結(jié)束
通過(guò)下面的示例可以很輕松地理解這一過(guò)程(GEN_RUNNING
這個(gè)狀態(tài)只有在多線程中才能觀察到,這里就不演示啦)
>>> gen = (x for x in range(2))
>>> from inspect import getgeneratorstate
>>> gen = (x for x in range(3))
>>> getgeneratorstate(gen)
'GEN_CREATED'
>>>
>>> next(gen)
0
>>> getgeneratorstate(gen)
'GEN_SUSPENDED'
>>> next(gen)
1
>>> next(gen)
Traceback (most recent call last):
File "", line 1, in
StopIteration
>>> getgeneratorstate(gen)
'GEN_CLOSED'
6. 生成器的異常
在最前面,我有定義了一個(gè)生成器函數(shù)。
def generator_factory(top=2):
index = 0
while index < top:
index = index + 1
yield index
raise StopIteration
在沒(méi)有元素可返回時(shí),我最后拋出了 StopIteration
異常,這是為了滿足生成器的協(xié)議。
實(shí)際上,如果你不手動(dòng)拋出 StopIteration
,在生成器遇到函數(shù) return 時(shí),會(huì)我自動(dòng)拋出 StopIteration
。
請(qǐng)看下面代碼,我將 raise StopIteration
去掉后,仍然會(huì)拋出異常。
>>> def generator_factory(top=2):
... index = 0
... while index < top:
... index = index + 1
... yield index
...
>>> gen = generator_factory()
>>> next(gen)
1
>>> next(gen)
2
>>> next(gen)
Traceback (most recent call last):
File "", line 1, in
StopIteration
審核編輯:符乾江
-
生成器
+關(guān)注
關(guān)注
7文章
320瀏覽量
21149 -
python
+關(guān)注
關(guān)注
56文章
4811瀏覽量
85075
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
開(kāi)源隨機(jī)數(shù)生成器庫(kù)OpenRNG助力實(shí)現(xiàn)移植到Arm平臺(tái)時(shí)的最佳性能
![開(kāi)源隨機(jī)數(shù)<b class='flag-5'>生成器</b>庫(kù)OpenRNG助力實(shí)現(xiàn)移植到Arm平臺(tái)時(shí)的最佳性能](https://file1.elecfans.com/web3/M00/07/82/wKgZO2emstiAAcxyAAAT-fClqro271.png)
超詳細(xì)!FMU生成器用戶手冊(cè)來(lái)啦~
![超詳細(xì)!FMU<b class='flag-5'>生成器</b>用戶手冊(cè)來(lái)啦~](https://file.elecfans.com/web2/M00/40/07/pYYBAGJrUk2AaMaTAAAQONQtdzo461.jpg)
EE-322:面向SHARC處理器的專家代碼生成器
![EE-322:面向SHARC處理器的專家代碼<b class='flag-5'>生成器</b>](https://file.elecfans.com/web1/M00/D9/4E/pIYBAF_1ac2Ac0EEAABDkS1IP1s689.png)
使用C2000?嵌入式模式生成器(EPG)進(jìn)行設(shè)計(jì)
![使用C2000?嵌入式模式<b class='flag-5'>生成器</b>(EPG)進(jìn)行設(shè)計(jì)](https://file.elecfans.com/web1/M00/D9/4E/pIYBAF_1ac2Ac0EEAABDkS1IP1s689.png)
Freepik攜手Magnific AI推出AI圖像生成器
CDCM6208V1F具有小數(shù)分頻器的2:8時(shí)鐘生成器/抖動(dòng)消除器數(shù)據(jù)表
![CDCM6208V1F具有小數(shù)分頻器的2:8時(shí)鐘<b class='flag-5'>生成器</b>/抖動(dòng)消除器數(shù)據(jù)表](https://file.elecfans.com/web1/M00/D9/4E/pIYBAF_1ac2Ac0EEAABDkS1IP1s689.png)
具有小數(shù)分頻器的CDCM6208 2:8時(shí)鐘生成器/抖動(dòng)消除器數(shù)據(jù)表
![具有小數(shù)分頻器的CDCM6208 2:8時(shí)鐘<b class='flag-5'>生成器</b>/抖動(dòng)消除器數(shù)據(jù)表](https://file.elecfans.com/web1/M00/D9/4E/pIYBAF_1ac2Ac0EEAABDkS1IP1s689.png)
TSMaster 測(cè)試報(bào)告生成器操作指南
![TSMaster 測(cè)試報(bào)告<b class='flag-5'>生成器</b>操作指南](https://file.elecfans.com/web2/M00/40/07/pYYBAGJrUk2AaMaTAAAQONQtdzo461.jpg)
生成對(duì)抗網(wǎng)絡(luò)(GANs)的原理與應(yīng)用案例
微軟Edge瀏覽器將引入AI主題生成器,為用戶提供獨(dú)特的主頁(yè)設(shè)計(jì)
飛凌嵌入式ElfBoard ELF 1板卡-在線二維碼生成器
如何使用Python生成四位隨機(jī)數(shù)字
![](https://file1.elecfans.com/web2/M00/C6/E0/wKgZomYNCkmAGJf2AAKIIXI8xYA361.png)
深度學(xué)習(xí)生成對(duì)抗網(wǎng)絡(luò)(GAN)全解析
![深度學(xué)習(xí)<b class='flag-5'>生成</b>對(duì)抗網(wǎng)絡(luò)(GAN)全解析](https://file1.elecfans.com/web2/M00/C6/3B/wKgZomYGY4qACxMuAAATTUiS7WI899.png)
評(píng)論