生成器介紹
在函數(shù)內(nèi)部包含yield關(guān)鍵字,那么該函數(shù)執(zhí)行的結(jié)果是生成器培慌,生成器就是迭代器。
生成器的功能:把函數(shù)結(jié)果做成迭代器(以一種優(yōu)雅的方式封裝好iter,next)。提供了一種自己定義迭代器的方式镐牺。
使用生成器創(chuàng)建一個(gè)迭代器:
def a():
print('a')
yield 11 # 使用yield,執(zhí)行后返回魁莉,類似于return,但是直接執(zhí)行函數(shù)會(huì)生成一個(gè)迭代器
print('b')
yield 22
print('c')
yield '33'
g=a()
for i in g: # i=iter(g) g=next(i) #這里只執(zhí)行迭代過程睬涧,迭代的內(nèi)容是一個(gè)函數(shù)
pass
輸出結(jié)果:
a
b
c
此處的i
做為迭代器中的一個(gè)元素,在執(zhí)行之后會(huì)將yield
的返回值沛厨,賦值給i
宙地,打印i
就可以得到返回值:
def a():
print('a')
yield 11
print('b')
yield 22
print('c')
yield '33'
g=a()
for i in g: # i=iter(g) next(i)
print(i)
執(zhí)行結(jié)果:
a
11
b
22
c
33
生成器作用
使用生成器創(chuàng)建迭代器,在使用大容量列表或者對(duì)大文件進(jìn)行操作的時(shí)候?yàn)榱吮苊鈨?nèi)存被耗盡會(huì)使用迭代器的方式去實(shí)現(xiàn)逆皮。
創(chuàng)建迭代器:
def my_rang(start,stop):
while True:
if start == stop:
raise StopIteration # 主動(dòng)拋出一個(gè)異常宅粥,結(jié)束迭代器。
yield start
start+=1
g=my_rang(1,10)
for i in g:
print(i)
提示:不要使用控制循環(huán)的方式控制迭代器退出电谣,這樣會(huì)產(chǎn)生迭代器異常秽梅,最好使用主動(dòng)拋出
raise StopIteration
的方式去終止迭代器。
yield與return的比較
都有返回值的功能剿牺,return只能返回一次值企垦,yield能返回多次值。
yield的功能:
- 把函數(shù)的結(jié)果做成迭代器(以一種優(yōu)雅的方式封裝好iter,next)
- 函數(shù)暫停與再繼續(xù)運(yùn)行的狀態(tài)是由yield提供的晒来。
生成器與迭代器的應(yīng)用
讀取文件钞诡,模擬Linux 系統(tǒng)中的tail 功能。
import time
def tail(filename):
with open(filename,'r') as f:
f.seek(0,2)
while True:
line=f.readline()
if line:
yield (line)
else:
time.sleep(0.3)
for g in tail('a.txt'):
print(g)
當(dāng)向文件中追加內(nèi)容時(shí)湃崩,會(huì)自動(dòng)顯示追加的新內(nèi)容荧降。
同理,如果實(shí)現(xiàn)管道功能,使用grep類似的功能,只需添加一個(gè)grep 函數(shù)即可:
import time
def tail(filename):
with open(filename,'r') as f:
f.seek(0,2)
while True:
line=f.readline()
if line:
yield (line)
else:
time.sleep(0.3)
def grep(patten,lines):
for line in lines:
if patten in line:
print(line,end='')
grep('error',tail('a.txt'))
這樣就避免了占用過大內(nèi)存的情況,內(nèi)存中只保存一行數(shù)據(jù).