Python生成器以及應(yīng)用

生成器可以理解為一種數(shù)據(jù)類型,這種數(shù)據(jù)類型自動實(shí)現(xiàn)了迭代器協(xié)議(其它的數(shù)據(jù)類型需要調(diào)用自己內(nèi)置的_iter_方法),所以生成器就是可迭代對象。Python有兩種不同的方式提供生成器。

1. 生成器函數(shù):使用yield 而不是return語句返回結(jié)果。yield語句一次返回一個(gè)結(jié)果。在每個(gè)結(jié)果中間,掛起函數(shù)的狀態(tài),以便下次從它離開的地方繼續(xù)執(zhí)行。yield函數(shù)的功能:

a. 把函數(shù)的結(jié)果做生迭代器(以一種優(yōu)雅的方式封裝好_iter_, _next_)

b. 函數(shù)的暫停與再繼續(xù)運(yùn)行有yield控制

yield與return的比較:

相同點(diǎn):都有返回值的功能

不同點(diǎn):return只能返回一次值,yield可以返回多次值

2. 生成器表達(dá)式:類似于列表推導(dǎo)。但是,生成器返回按需產(chǎn)生結(jié)果的一個(gè)對象,而不是一次構(gòu)建一個(gè)結(jié)果列表。如

g=('egg%s' %i for i in range(1000))

print(g)

print(next(g))

print(next(g))

print(next(g))

生成器應(yīng)用:讀取大文件:如:

有一個(gè)文件有1T左右,并且只有一行,行之間有分隔符,我們需要把文件內(nèi)的數(shù)據(jù)一行一行讀取出來,然后寫入數(shù)據(jù)庫里面。

分析:遇到超大文件,不能直接放在內(nèi)存中。要分段進(jìn)行讀取,以減少內(nèi)存的占用

由于它只有一行,如果這樣讀取的話,1T 內(nèi)存誰也承受不了

with open("file","r") as f:

for i in f.readlines()

? ? ? ? print(i)

除了f.readlines(),可以用另外一個(gè)函數(shù) file.read()

1.f.read() 函數(shù)并不是一次讀取所有,可以傳入 int 參數(shù),代表讀取的字符數(shù)

2.連續(xù)調(diào)用,可以讀取偏移量的值 。

import os

filepath = os.path.dirname(os.path.abspath('.'))+"http://a.txt"

def Myread(f,newlineseperator):

buffer ='' #暫存讀取的數(shù)據(jù)

? ? while True:

while newlineseperatorin buffer:#判斷 分隔符是否存在暫存數(shù)據(jù)

? ? ? ? ? ? pos = buffer.index(newlineseperator)#用了index方法并且返回分隔符的下表

? ? ? ? ? ? yield buffer[:pos]#取分隔符前面的值保存在生成器

? ? ? ? ? ? buffer=buffer[pos+len(newlineseperator):]#取過值也更新buffer,刪除前面取得值加上分隔符

? ? ? ? chunk = f.read(50)# 一次50個(gè)字符

? ? ? ? if not chunk:#如果取不到值了,就用這個(gè)結(jié)束循環(huán)

? ? ? ? ? ? yield buffer#最后一個(gè)分隔符后邊的值加上再次取到的chunk值

? ? ? ? ? ? break

? ? ? ? buffer = buffer + chunk

with open(filepath,"r")as f:

for iin Myread(f,newlineseperator="{|}"):

print(i)

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容