
还在为大数据处理发愁?每次处理个大文件、大序列,电脑就卡得要死,内存直接飙红?别担心,生成器来救场了!它能帮你用更少的内存处理更复杂的任务。今天就通过 5 个实战案例,带你掌握生成器的核心用法,大幅提升代码效率!
在讲具体的生成器函数之前,先给新手朋友补补课。生成器其实就是一种特殊的函数,它里面用了yield关键字,而不是普通函数的return。
yield就像是个暂停按钮,当生成器运行到yield时,会把后面的值返回出去,然后暂停在这儿,等下次再调用生成器时,就从这个暂停的地方接着往下跑。
这种特性就让生成器实现了 “按需生成”,不会一下子把所有数据都生成出来存到内存里,而是用一个取一个,内存占用特别低,对于处理大数据、流式数据来说,简直是神器!
斐波那契数列大家都不陌生,就是从 0 和 1 开始,后面每个数都是前两个数相加,像 0、1、1、2、3、5、8...
如果用普通函数来生成,要是想生成很大的数列,就得把所有数都存到列表里,数据量大了内存根本扛不住。但用生成器就不一样了,它能按需生成,用多少生成多少,内存占用极低。
def fibonacci_generator():
a, b = 0, 1
while True:
yield a
a, b = b, a + b
# 使用生成器
fib_gen = fibonacci_generator()
# 生成前10个斐波那契数
for i in range(10):
print(next(fib_gen), end=' ')
# 输出:0 1 1 2 3 5 8 13 21 34在这个代码里,fibonacci_generator函数就是一个生成器。我们调用它的时候,不会一下子生成所有的斐波那契数,而是每次调用next(fib_gen),它才会生成下一个数。
这个生成器在数学计算、算法演示等场景特别好用,比如在讲递归、迭代算法的时候,用它来演示斐波那契数列的生成过程,既直观又不占内存。对于那些需要处理无限或超大数据序列的场景,它也能轻松应对。
咱们平时用read()或者readlines()读取文件,会把整个文件内容都加载到内存里。要是遇到几个 GB 的大文件,内存直接就爆了,程序卡崩是常有的事。
但用生成器逐行读取就不一样了,它每次只读取一行内容,处理完这一行,再读取下一行,内存里始终只保留一行数据,轻松解决内存不足的问题。
def read_large_file(file_path):
with open(file_path, 'r', encoding='utf-8') as file:
for line in file:
yield line.strip() # 去除每行末尾的换行符等空白字符
# 使用生成器读取大文件
file_path = 'large_file.txt' # 假设这是一个GB级的大文件
for line in read_large_file(file_path):
# 在这里处理每行数据,比如进行日志分析、数据清洗等
print(line)这里用with语句打开文件,能保证文件用完后自动关闭。然后通过for line in file逐行读取,再用yield返回每行内容,这样就实现了流式处理。
日志分析、数据清洗等需要流式处理的任务,用这个生成器再合适不过了。不管文件多大,都能平稳处理,不会出现内存不够的情况。
有时候我们需要实时计算累加值,比如统计实时数据流的总和。要是用普通方法,得定义一个变量不断累加,代码显得有点繁琐。
累加和生成器就能帮我们简化这个过程,它可以边接收数据边计算累加值,实时反馈结果,代码简洁又高效。
def accumulator_generator():
total = 0
while True:
num = yield total
if num is None:
break
total += num
# 使用累加和生成器
acc_gen = accumulator_generator()
next(acc_gen) # 启动生成器,让它运行到yield处
print(acc_gen.send(5)) # 发送数据5,返回累加和5
print(acc_gen.send(3)) # 发送数据3,返回累加和8
print(acc_gen.send(2)) # 发送数据2,返回累加和10
acc_gen.close() # 关闭生成器这个生成器里,yield total会先返回当前的累加和,然后等待接收下一个数据。我们通过send()方法发送数据,生成器会把数据赋给num,然后进行累加。
实时统计、数据流处理等场景,比如实时统计网站的访问量、传感器数据的累计值等,用它能很方便地实现。
有时候我们需要循环生成指定的序列,比如构造测试数据的时候,需要重复生成一些固定的测试用例。要是手动写循环逻辑,代码会比较冗余。
无限重复生成器就能帮我们解决这个问题,它可以循环生成指定的序列,不用我们手动处理循环逻辑。
def repeat_generator(sequence):
while True:
for item in sequence:
yield item
# 使用无限重复生成器
seq = [1, 2, 3]
rep_gen = repeat_generator(seq)
# 生成前7个值
for i in range(7):
print(next(rep_gen), end=' ')
# 输出:1 2 3 1 2 3 1在这个生成器里,通过while True实现无限循环,然后在里面遍历指定的序列,用yield返回每个元素,这样就实现了对序列的无限重复生成。
测试数据构造、循环场景简化等。比如在进行压力测试时,需要不断发送相同的请求数据,就可以用这个生成器来生成。
处理大规模的 CSV 表格数据时,如果用普通方法一次性加载所有数据,很容易导致内存过载。CSV 行读取生成器可以分块处理 CSV 文件,按需生成数据行,配合 CSV 模块高效解析,能避免内存问题,提升数据处理稳定性。
import csv
def csv_reader_generator(file_path):
with open(file_path, 'r', encoding='utf-8') as csvfile:
reader = csv.reader(csvfile)
for row in reader:
yield row
# 使用CSV行读取生成器
csv_path = 'large_data.csv' # 假设这是一个大规模的CSV文件
csv_gen = csv_reader_generator(csv_path)
for row in csv_gen:
# 处理每行数据,比如分析表格中的信息
print(row)这里导入了csv模块,用csv.reader来解析 CSV 文件,然后通过生成器逐行返回数据,实现了对大规模 CSV 文件的流式处理。
应对大规模表格数据处理,比如处理大型的用户数据表格、交易记录表格等。
生成器函数 | 功能 | 适用场景 | 核心特点 |
|---|---|---|---|
斐波那契数列生成器 | 按需生成无限斐波那契数列 | 数学计算、算法演示等 | 内存占用极低,可处理无限或超大数据序列 |
文件逐行读取生成器 | 逐行读取大文件 | 日志分析、数据清洗等流式处理任务 | 避免一次性加载全部内容,解决内存不足问题 |
累加和生成器 | 实时计算累加值,支持动态输入 | 实时统计、数据流处理等 | 边接收边计算,实时反馈结果,代码简洁高效 |
无限重复生成器 | 循环生成指定序列 | 测试数据构造、循环场景简化等 | 无需手动处理循环逻辑,减少代码冗余 |
CSV 行读取生成器 | 分块处理 CSV 文件,按需生成数据行 | 大规模表格数据处理 | 配合 CSV 模块高效解析,避免内存过载 |
生成器是一次性的,遍历完一次后,里面就没有数据了,再次遍历不会有结果。
比如下面的代码:
gen = (x for x in range(3))
for num in gen:
print(num) # 输出:0 1 2
for num in gen:
print(num) # 没有输出解决办法:如果需要多次遍历,就把生成器转换成列表,list(gen),不过这样会占用更多内存,要根据实际情况选择。
生成器函数里不能用return返回值,否则会抛出StopIteration异常。
def wrong_generator():
yield 1
return 2 # 会报错
gen = wrong_generator()
next(gen) # 输出1
next(gen) # 抛出StopIteration异常解决办法:生成器里不要用return返回值,如果要结束生成器,可以直接让函数运行结束,或者用raise StopIteration。
使用send()方法给生成器发送数据之前,必须先启动生成器,也就是先调用一次next(),让生成器运行到yield处。
def my_generator():
num = yield
print(num)
gen = my_generator()
gen.send(5) # 会报错解决办法:在调用send()之前,先调用next(gen)启动生成器。
生成器是一种特殊的函数,它使用yield关键字来返回值,而普通函数用return。生成器运行到yield时会暂停并返回值,下次调用时从暂停的地方继续运行;普通函数一旦遇到return就会结束,再次调用会重新开始。另外,生成器能实现惰性计算,内存占用低,适合处理大数据。
yield关键字有两个主要作用,一是把值返回给调用者,二是让生成器暂停运行,保存当前的状态,等下次调用生成器时,从这个暂停的地方继续往下执行。
生成器最大的优势是内存占用低,因为它是按需生成数据,不会一次性把所有数据都加载到内存里。另外,生成器代码简洁,能简化循环和迭代的逻辑,适合处理大数据、流式数据等场景。
生成器是一种特殊的迭代器,它自动实现了迭代器的__iter__()和__next__()方法,所以生成器可以直接用于迭代。迭代器需要手动实现这两个方法,而生成器通过yield关键字更方便地实现了迭代功能。
生成器通过yield关键字实现 “按需生成”,内存占用低、延迟加载,是处理大数据、流式数据的必备技能。
今天讲的这 5 个生成器函数 —— 斐波那契数列生成器、文件逐行读取生成器、累加和生成器、无限重复生成器、CSV 行读取生成器,在不同的场景下都能发挥很大的作用。
无论是新手还是进阶开发者,掌握这些案例都能写出更优雅、高效的代码。希望大家能好好理解和运用生成器,让自己的 Python 代码更上一层楼!
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。