1.生成器(generator)概念
生成器是迭代器馒稍,生成器提供了非常方便的自定義迭代器的途徑,在Python中,這種一邊循環(huán)一邊計(jì)算的機(jī)制缓艳,稱為生成器(Generator)
2.生成器作用
通過(guò)列表生成式昂秃,我們可以直接創(chuàng)建一個(gè)列表椎瘟。但是,受到內(nèi)存限制呀潭,列表容量肯定是有限的钉迷。而且,創(chuàng)建一個(gè)包含100萬(wàn)個(gè)元素的列表钠署,不僅占用很大的存儲(chǔ)空間糠聪,如果我們僅僅需要訪問(wèn)前面幾個(gè)元素,那后面絕大多數(shù)元素占用的空間都白白浪費(fèi)了谐鼎。所以舰蟆,如果列表元素可以按照某種算法推算出來(lái)趣惠,那我們是否可以在循環(huán)的過(guò)程中不斷推算出后續(xù)的元素呢?這樣就不必創(chuàng)建完整的list身害,從而節(jié)省大量的空間.
比如味悄,著名的斐波拉契數(shù)列(Fibonacci),除第一個(gè)和第二個(gè)數(shù)外塌鸯,任意一個(gè)數(shù)都可由前兩個(gè)數(shù)相加得到:
1, 1, 2, 3, 5, 8, 13, 21, 34, ...
斐波拉契常規(guī)函數(shù)寫法:
In [18]: def fib(num):
...: a,b,n=0,1,0
...: while n<num:
...: print(b)
...: a,b=b,a+b
...: n+=1
...:
In [19]: fib(5)
1
1
2
3
5
3.生成器創(chuàng)建
常見(jiàn)的生成器創(chuàng)建有兩種形式:
①生成器表達(dá)式
②生成器函數(shù)
3.1.生成器表達(dá)式
生成器表達(dá)式與列表解析式極為相似,將列表解析式'[]'改成'()'就是一個(gè)生成器,生成器擁有next方法并且行為與迭代器完全相同侍瑟,這意味著生成器也可以用于Python的for循環(huán)遍歷,看
In [16]: gen=(x*x for x in range(4))
In [17]: gen
Out[17]: <generator object <genexpr> at 0x00000000045335E8> #結(jié)果表明為生成器
In [18]: for i in gen :
print(i),
#執(zhí)行結(jié)果
0 1 4 9
3.1.生成器函數(shù)
生成器函數(shù)與普通函數(shù)極為相似,若函數(shù)中包含了至少一個(gè)yield關(guān)鍵字則為生成器,通過(guò)生成器函數(shù)可實(shí)現(xiàn)復(fù)雜邏輯的generator,例:
#定義一個(gè)生成器
In [1]: def gen():
print('start')
for i in range(5):
yield i #帶yield關(guān)鍵字
print(i)
print('end')
------------------------------------------------------------------------------
In [2]: gen()
Out[2]: <generator object gen at 0x0000000004533C18> #結(jié)果表明為生成器
In [3]: t=gen()
In [4]: next(t) #每次進(jìn)行迭代時(shí)返回一個(gè)值
start
Out[4]: 0
In [5]: next(t)
0
Out[5]: 1
In [6]: next(t)
1
Out[6]: 2
In [7]: next(t)
2
Out[7]: 3
In [8]: next(t)
3
Out[8]: 4
In [9]: next(t)
4
end
--------------------- 執(zhí)行到末尾,迭代器遇到StopIteration異常結(jié)束
StopIteration Traceback (most recent call last)
<ipython-input-9-9494367a8bed> in <module>()
----> 1 next(t)
StopIteration:
4.生成器函數(shù)執(zhí)行過(guò)程
生成器函數(shù)中的yield關(guān)鍵字包含兩種功能:
1.返回
2.掛起
[L1] def gen():
[L2] print('start')
[L3] for i in range(5):
[L4] yield i
[L5] print(i)
[L6] print('end')
1.第一次執(zhí)行next(generator)時(shí),會(huì)執(zhí)行完yield語(yǔ)句后程序進(jìn)行掛起丙猬,所有的參數(shù)和狀態(tài)會(huì)進(jìn)行保存
2.再一次執(zhí)行next(generator)時(shí)涨颜,會(huì)從掛起的狀態(tài)開(kāi)始往后執(zhí)行。
在遇到程序的結(jié)尾或者遇到StopIteration時(shí)茧球,循環(huán)結(jié)束
yield 與 return
5.生成器自帶方法屬性
#在ipython中對(duì)之前創(chuàng)建的gen生成器對(duì)象查看幫助
In [20]: help(gen)
Help on generator object:
<genexpr> = class generator(object)
| Methods defined here:
|
| __getattribute__(...)
| x.__getattribute__('name') <==> x.name
|
| __iter__(...)
| x.__iter__() <==> iter(x)
|
| __repr__(...)
| x.__repr__() <==> repr(x)
|
| close(...)
| close() -> raise GeneratorExit inside generator.
|
| next(...)
| x.next() -> the next value, or raise StopIteration
|
| send(...)
| send(arg) -> send 'arg' into generator,
| return next yielded value or raise StopIteration.
|
| throw(...)
| throw(typ[,val[,tb]]) -> raise exception in generator,
| return next yielded value or raise StopIteration.
|
| ----------------------------------------------------------------------
| Data descriptors defined here:
|
| gi_code
|
| gi_frame
|
| gi_running
通過(guò)上面的幫助文件可以歸納出生成器的方法有
1.close()
手動(dòng)關(guān)閉生成器函數(shù)庭瑰,后面的調(diào)用會(huì)直接返回StopIteration異常。
2.send()
生成器函數(shù)最大的特點(diǎn)是可以接受外部傳入的一個(gè)變量抢埋,并根據(jù)變量?jī)?nèi)容計(jì)算結(jié)果后返回
3.throw()
用來(lái)向生成器函數(shù)送入一個(gè)異常弹灭,可以結(jié)束系統(tǒng)定義的異常,或者自定義的異常揪垄。
throw()后直接跑出異常并結(jié)束程序穷吮,或者消耗掉一個(gè)yield,或者在沒(méi)有下一個(gè)yield的時(shí)候直接進(jìn)行到程序的結(jié)尾饥努。