首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >工作了这么久才知道的5大Python生成器函数!

工作了这么久才知道的5大Python生成器函数!

原创
作者头像
小白的大数据之旅
发布2025-08-29 10:06:48
发布2025-08-29 10:06:48
5610
举报

工作了这么久才知道的 5 大 Python 生成器函数!

还在为大数据处理发愁?每次处理个大文件、大序列,电脑就卡得要死,内存直接飙红?别担心,生成器来救场了!它能帮你用更少的内存处理更复杂的任务。今天就通过 5 个实战案例,带你掌握生成器的核心用法,大幅提升代码效率!

一、啥是生成器?先简单唠唠

在讲具体的生成器函数之前,先给新手朋友补补课。生成器其实就是一种特殊的函数,它里面用了yield关键字,而不是普通函数的return

yield就像是个暂停按钮,当生成器运行到yield时,会把后面的值返回出去,然后暂停在这儿,等下次再调用生成器时,就从这个暂停的地方接着往下跑。

这种特性就让生成器实现了 “按需生成”,不会一下子把所有数据都生成出来存到内存里,而是用一个取一个,内存占用特别低,对于处理大数据、流式数据来说,简直是神器!

二、5 大实用生成器函数实战

1. 斐波那契数列生成器

斐波那契数列大家都不陌生,就是从 0 和 1 开始,后面每个数都是前两个数相加,像 0、1、1、2、3、5、8...

如果用普通函数来生成,要是想生成很大的数列,就得把所有数都存到列表里,数据量大了内存根本扛不住。但用生成器就不一样了,它能按需生成,用多少生成多少,内存占用极低。

代码示例
代码语言:python
复制
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),它才会生成下一个数。

适用场景

这个生成器在数学计算、算法演示等场景特别好用,比如在讲递归、迭代算法的时候,用它来演示斐波那契数列的生成过程,既直观又不占内存。对于那些需要处理无限或超大数据序列的场景,它也能轻松应对。

2. 文件逐行读取生成器

咱们平时用read()或者readlines()读取文件,会把整个文件内容都加载到内存里。要是遇到几个 GB 的大文件,内存直接就爆了,程序卡崩是常有的事。

但用生成器逐行读取就不一样了,它每次只读取一行内容,处理完这一行,再读取下一行,内存里始终只保留一行数据,轻松解决内存不足的问题。

代码示例
代码语言:python
复制
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返回每行内容,这样就实现了流式处理。

适用场景

日志分析、数据清洗等需要流式处理的任务,用这个生成器再合适不过了。不管文件多大,都能平稳处理,不会出现内存不够的情况。

3. 累加和生成器

有时候我们需要实时计算累加值,比如统计实时数据流的总和。要是用普通方法,得定义一个变量不断累加,代码显得有点繁琐。

累加和生成器就能帮我们简化这个过程,它可以边接收数据边计算累加值,实时反馈结果,代码简洁又高效。

代码示例
代码语言:python
复制
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,然后进行累加。

适用场景

实时统计、数据流处理等场景,比如实时统计网站的访问量、传感器数据的累计值等,用它能很方便地实现。

4. 无限重复生成器

有时候我们需要循环生成指定的序列,比如构造测试数据的时候,需要重复生成一些固定的测试用例。要是手动写循环逻辑,代码会比较冗余。

无限重复生成器就能帮我们解决这个问题,它可以循环生成指定的序列,不用我们手动处理循环逻辑。

代码示例
代码语言:python
复制
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返回每个元素,这样就实现了对序列的无限重复生成。

适用场景

测试数据构造、循环场景简化等。比如在进行压力测试时,需要不断发送相同的请求数据,就可以用这个生成器来生成。

5. CSV 行读取生成器

处理大规模的 CSV 表格数据时,如果用普通方法一次性加载所有数据,很容易导致内存过载。CSV 行读取生成器可以分块处理 CSV 文件,按需生成数据行,配合 CSV 模块高效解析,能避免内存问题,提升数据处理稳定性。

代码示例
代码语言:python
复制
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 文件的流式处理。

适用场景

应对大规模表格数据处理,比如处理大型的用户数据表格、交易记录表格等。

三、5 大生成器函数对比表格

生成器函数

功能

适用场景

核心特点

斐波那契数列生成器

按需生成无限斐波那契数列

数学计算、算法演示等

内存占用极低,可处理无限或超大数据序列

文件逐行读取生成器

逐行读取大文件

日志分析、数据清洗等流式处理任务

避免一次性加载全部内容,解决内存不足问题

累加和生成器

实时计算累加值,支持动态输入

实时统计、数据流处理等

边接收边计算,实时反馈结果,代码简洁高效

无限重复生成器

循环生成指定序列

测试数据构造、循环场景简化等

无需手动处理循环逻辑,减少代码冗余

CSV 行读取生成器

分块处理 CSV 文件,按需生成数据行

大规模表格数据处理

配合 CSV 模块高效解析,避免内存过载

四、常见问题和错误

1. 生成器只能遍历一次

生成器是一次性的,遍历完一次后,里面就没有数据了,再次遍历不会有结果。

比如下面的代码:

代码语言:python
复制
gen = (x for x in range(3))

for num in gen:

   print(num)  # 输出:0 1 2

for num in gen:

   print(num)  # 没有输出

解决办法:如果需要多次遍历,就把生成器转换成列表,list(gen),不过这样会占用更多内存,要根据实际情况选择。

2. 在生成器中使用 return 会报错

生成器函数里不能用return返回值,否则会抛出StopIteration异常。

代码语言:python
复制
def wrong_generator():

   yield 1

   return 2  # 会报错

gen = wrong_generator()

next(gen)  # 输出1

next(gen)  # 抛出StopIteration异常

解决办法:生成器里不要用return返回值,如果要结束生成器,可以直接让函数运行结束,或者用raise StopIteration

3. 忘记启动生成器

使用send()方法给生成器发送数据之前,必须先启动生成器,也就是先调用一次next(),让生成器运行到yield处。

代码语言:python
复制
def my_generator():

   num = yield

   print(num)

gen = my_generator()

gen.send(5)  # 会报错

解决办法:在调用send()之前,先调用next(gen)启动生成器。

五、面试时可能会问到的问题及回答

1. 什么是生成器?它和普通函数有什么区别?

生成器是一种特殊的函数,它使用yield关键字来返回值,而普通函数用return。生成器运行到yield时会暂停并返回值,下次调用时从暂停的地方继续运行;普通函数一旦遇到return就会结束,再次调用会重新开始。另外,生成器能实现惰性计算,内存占用低,适合处理大数据。

2. yield 关键字的作用是什么?

yield关键字有两个主要作用,一是把值返回给调用者,二是让生成器暂停运行,保存当前的状态,等下次调用生成器时,从这个暂停的地方继续往下执行。

3. 生成器有什么优势?

生成器最大的优势是内存占用低,因为它是按需生成数据,不会一次性把所有数据都加载到内存里。另外,生成器代码简洁,能简化循环和迭代的逻辑,适合处理大数据、流式数据等场景。

4. 生成器和迭代器有什么关系?

生成器是一种特殊的迭代器,它自动实现了迭代器的__iter__()__next__()方法,所以生成器可以直接用于迭代。迭代器需要手动实现这两个方法,而生成器通过yield关键字更方便地实现了迭代功能。

六、总结

生成器通过yield关键字实现 “按需生成”,内存占用低、延迟加载,是处理大数据、流式数据的必备技能。

今天讲的这 5 个生成器函数 —— 斐波那契数列生成器、文件逐行读取生成器、累加和生成器、无限重复生成器、CSV 行读取生成器,在不同的场景下都能发挥很大的作用。

无论是新手还是进阶开发者,掌握这些案例都能写出更优雅、高效的代码。希望大家能好好理解和运用生成器,让自己的 Python 代码更上一层楼!

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

目录
  • 工作了这么久才知道的 5 大 Python 生成器函数!
    • 一、啥是生成器?先简单唠唠
    • 二、5 大实用生成器函数实战
      • 1. 斐波那契数列生成器
      • 2. 文件逐行读取生成器
      • 3. 累加和生成器
      • 4. 无限重复生成器
      • 5. CSV 行读取生成器
    • 三、5 大生成器函数对比表格
    • 四、常见问题和错误
      • 1. 生成器只能遍历一次
      • 2. 在生成器中使用 return 会报错
      • 3. 忘记启动生成器
    • 五、面试时可能会问到的问题及回答
      • 1. 什么是生成器?它和普通函数有什么区别?
      • 2. yield 关键字的作用是什么?
      • 3. 生成器有什么优势?
      • 4. 生成器和迭代器有什么关系?
    • 六、总结
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档