生成器是根據算法生成數據的一種機制,每次調用生成器只生成一個值,可以節省大量內存
生成器推導式
gg = ( i * 2 for i in range(5))print(gg)print(next(gg)) # 0
print(next(gg)) # 2
print(next(gg)) # 4
print(next(gg)) # 6
print(next(gg)) # 8
yield關鍵字
def generater(num):for i in range(num):print("開始")yield iprint("生成完成")g = generater(2)print( next(g) )
print( next(g) )
print( next(g) )"""
開始
0
生成完成
開始
1
生成完成
Traceback (most recent call last):File "d:\Code\PythonProject\with\Generator2.py", line 11, in <module>print( next(g) )^^^^^^^
StopIteration
"""
def generater(num):for i in range(num):print("開始")yield iprint("生成完成")g = generater(5)for i in g:print(i)
"""
不會報錯
"""
生成器的核心思想是??惰性計算??。它不會一次性把所有數據都計算出來并存儲在內存中,而是“需要的時候才計算,每次只給你一個”。
假設有一個幾十GB的日志文件,你需要逐行處理。
def read_file_to_list(filename):result = [] # 創建一個空列表with open(filename) as f:for line in f:result.append(line) # 將每一行都添加到列表中return result # 返回一個包含所有行的巨大列表data = read_file_to_list('huge_log.log') # 內存爆炸!
for line in data:process(line)
??問題??:result
列表會嘗試將所有文件內容加載到內存中,如果文件極大,會消耗巨量內存甚至導致程序崩潰。
def read_file_by_line(filename):with open(filename) as f:for line in f: yield line # 關鍵在這里:使用yielddata_generator = read_file_by_line('huge_log.log') # 幾乎不占內存
for line in data_generator: # 每次循環從文件里讀一行到內存process(line)
1. 調用read_file_by_line時候,函數不會立即執行,而是返回一個生成器對象,此時文件一行都沒讀
2. 在for循環中,每次迭代會從生成器中請求一個值(一行內容)
3. 生成器函數從上次暫停的yield處繼續執行,讀取文件的下一行,yield返回這行數據,然后立即暫停。