Python使用生成器輕松處理海量數(shù)據(jù)
不知道大家有沒有處理過海量數(shù)據(jù),就是數(shù)據(jù)量非常龐大的時候,如何處理?說實(shí)在的在實(shí)際項(xiàng)目中確實(shí)是沒有處理過海量數(shù)據(jù),但是沒事兒的時候我們可以在本地模擬海量數(shù)據(jù)來玩玩兒的,那么處理海量數(shù)據(jù)用什么方式呢?用readlines()讀???還是用生成器和迭代器呢?恐怕大家用的應(yīng)該也都是生成器和迭代器吧!要不然程序卡死不說,有可能把電腦搞崩潰呦!
那么生成器和迭代器怎么玩兒呢?咱們繼續(xù)往下走著看著。
從生活場景理解迭代器
想象一下你去吃自助餐,不是一次性把所有的食物都端到你桌上那得多大的桌子??!,而是想吃的時候去取一點(diǎn)。迭代器就是這樣的工作方式。(PS:有的人可能就是一次性端上來,個例個例,比喻不是很恰當(dāng))
在Python中,任何實(shí)現(xiàn)了__iter__()和__next__()方法的對象都是迭代器。它不會一次性把所有數(shù)據(jù)加載到內(nèi)存中,而是按需"生成"每個元素。
Python中很多內(nèi)置對象都是可迭代的:列表、元組、字符串、字典,甚至文件對象。這就是為什么你能用for循環(huán)遍歷它們的原因。
生成器:更優(yōu)雅的迭代器
寫迭代器需要定義類并實(shí)現(xiàn)兩個方法,有點(diǎn)麻煩。于是Python提供了更簡單的工具——生成器。
生成器有兩種創(chuàng)建方式:
1. 生成器函數(shù):使用def定義,但用yield代替return
def num_generator(num):
for i in range(num):
print(f"生成數(shù)字是:{i}")
yield i
# 使用創(chuàng)建的生成器
gen_a = num_generator(5)
# 逐個獲取值
for num in gen_a:
print(f"接收到:{num}")

2. 生成器表達(dá)式:類似列表推導(dǎo)式,但用圓括號
print("列表推導(dǎo)式VS生成器表達(dá)式:")
# 列表推導(dǎo)式-立即創(chuàng)建所有元素
list_comp = [x ** 2 for x in range(100000)]
# print(f"列表推導(dǎo)式:{list_comp}")
print(f"內(nèi)存占用:{list_comp.__sizeof__()}字節(jié)")
# 生成器表達(dá)式-按需生成元素
gen_comp = (x ** 2 for x in range(100000))
# print(f"生成器表達(dá)式:{gen_comp}")
print(f"內(nèi)存占用:{gen_comp.__sizeof__()}字節(jié)")

看看海量數(shù)據(jù)時,這個內(nèi)存占用大不大?害怕不害怕?
這個時候問題就來了:為什么生成器能高效處理大數(shù)據(jù)?為什么呢?
為什么生成器能高效處理大數(shù)據(jù)
這個主要就是生成器的一個執(zhí)行機(jī)制:
- 普通函數(shù):一旦調(diào)用,就從頭跑到尾(return),然后全部執(zhí)行完畢,局部變量全部銷毀。
- 生成器函數(shù)(使用
yield的函數(shù):如上面的第一幅截圖):調(diào)用時返回一個生成器對象,但并不立即執(zhí)行函數(shù)體。當(dāng)?shù)谝淮握{(diào)用next()時,函數(shù)從開始處執(zhí)行,直到遇到yield語句,暫停并返回 yield 后的值。函數(shù)當(dāng)前的整個局部狀態(tài)(變量、指針等)都會被凍結(jié)保存。 下次再調(diào)用next(),函數(shù)從上次暫停的yield語句后緊接著繼續(xù)執(zhí)行。
但是注意
生成器只能遍歷一次,如需重復(fù)使用需要重新創(chuàng)建,就是只能遍歷一次,再次打印已空空如也

生成器的高級用法
生成器不僅能產(chǎn)出數(shù)據(jù),還能通過send()方法接收數(shù)據(jù):
def interactive_generator():
while True:
received = yield # 等待發(fā)送數(shù)據(jù)
print(f"收到:{received}")
gen = interactive_generator()
next(gen) # 啟動生成器
gen.send("Hello") # 輸出:收到:Hello
gen.send("World") # 輸出:收到:World
這種方法在復(fù)雜的數(shù)據(jù)流水線處理中非常有用。
生成器和迭代器是Python處理海量數(shù)據(jù)的"神器",它們通過惰性計算(需要時才生成值)節(jié)省了大量內(nèi)存。 數(shù)據(jù)量不大時,用列表更簡單直接; 處理GB級別以上數(shù)據(jù)時,一定要用生成器;管道式數(shù)據(jù)處理中,生成器可以串聯(lián)形成高效處理鏈。
到此這篇關(guān)于Python使用生成器輕松處理海量數(shù)據(jù)的文章就介紹到這了,更多相關(guān)Python處理數(shù)據(jù)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
python對批量WAV音頻進(jìn)行等長分割的方法實(shí)現(xiàn)
這篇文章主要介紹了python對批量WAV音頻進(jìn)行等長分割的方法實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-09-09
使用 Python 實(shí)現(xiàn)微信群友統(tǒng)計器的思路詳解
這篇文章主要介紹了使用 Python 實(shí)現(xiàn)微信群友統(tǒng)計器的思路詳解,需要的朋友可以參考下2018-09-09
python實(shí)現(xiàn)接口并發(fā)測試腳本
這篇文章主要為大家詳細(xì)介紹了python實(shí)現(xiàn)接口并發(fā)測試腳本,具有一定的參考價值,感興趣的小伙伴們可以參考一下2019-06-06
Python語法糖for?else循環(huán)語句里的break使用詳解
這篇文章主要介紹了Python語法糖之for?else循環(huán)語句里的break使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-05-05
Python實(shí)現(xiàn)批量檢測ip地址連通性
這篇文章主要為大家詳細(xì)介紹了如何使用Python實(shí)現(xiàn)批量檢測ip地址連通性并以json格式顯示(支持傳參單IP或者網(wǎng)段),感興趣的小伙伴可以了解下2024-04-04
使用Matplotlib 繪制精美的數(shù)學(xué)圖形例子
今天小編就為大家分享一篇使用Matplotlib 繪制精美的數(shù)學(xué)圖形例子,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2019-12-12

