生成器是根据算法生成数据的一种机制,每次调用生成器只生成一个值,可以节省大量内存
生成器推导式
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返回这行数据,然后立即暂停。