共计 1647 个字符,预计需要花费 5 分钟才能阅读完成。
在 Python 中,生成器(Generator)是一种强大的数据生产机制,它能在需要时“动态生成”数据,而不是一次性在内存中创建所有数据。与普通函数不同,生成器使用 yield 关键字返回结果,每次调用时会从上次中断的地方继续执行,这种特性使得生成器特别适合处理大规模数据或流式数据。
一、生成器的基本概念
生成器本质上是一种特殊的迭代器,它能逐步生成数据,而不是一次性返回完整结果。
创建生成器有两种方式:
- 使用
yield关键字定义生成器函数; - 使用生成器表达式(类似于列表推导式)。
示例一:简单的生成器函数
def count_up_to(n):
i = 1
while i <= n:
yield i
i += 1
for num in count_up_to(5):
print(num)
输出结果:
1
2
3
4
5
解释:
每次循环到 yield 时函数会“暂停”,保存当前状态;下一次迭代时会从暂停处继续执行。
二、生成器表达式
生成器表达式语法与列表推导式类似,只是使用圆括号 ():
gen = (x * x for x in range(5))
for val in gen:
print(val)
输出:
0
1
4
9
16
相比列表推导式 [x * x for x in range(5)],生成器不会立即创建整个列表,而是每次迭代时才生成下一个值,从而节省大量内存。
三、生成器的惰性计算特性
生成器具备“惰性计算”(lazy evaluation)的特点,即按需生成数据,不会提前计算所有结果。
这在处理大文件、无限序列或网络流时特别有用。
示例:无限生成自然数
def infinite_numbers():
num = 1
while True:
yield num
num += 1
gen = infinite_numbers()
for _ in range(5):
print(next(gen))
输出:
1
2
3
4
5
生成器不会一次生成所有数据,而是每次请求一个新值。
四、next() 函数与 StopIteration 异常
生成器也是一种迭代器,可以使用 next() 手动获取下一个值:
g = (x for x in range(3))
print(next(g))
print(next(g))
print(next(g))
# print(next(g)) # StopIteration
当生成器没有更多内容可返回时,会抛出 StopIteration 异常,用于通知迭代结束。
五、在函数中使用 yield from
Python 3 引入了 yield from 语法,用于简化生成器的嵌套调用。
def sub_generator():
yield 1
yield 2
def main_generator():
yield from sub_generator()
yield 3
for i in main_generator():
print(i)
输出:
1
2
3
yield from 可以直接将子生成器的结果“转发”给外部循环,使代码更清晰。
六、生成器的实战应用
- 逐行读取大文件
def read_large_file(filename):
with open(filename, "r") as f:
for line in f:
yield line.strip()
for line in read_large_file("data.txt"):
print(line)
该方式在读取大文件时不会一次性加载整个文件,极大节省内存。
- 流式数据处理
在数据处理或日志分析中,生成器可用于实时处理数据流:
def squares(n):
for i in range(n):
yield i * i
result = sum(squares(1000000))
print(result)
相比使用列表的方式,这种写法不会占用大量内存,更高效。
七、小结
生成器是 Python 中实现高效迭代与惰性计算的核心机制。
要点总结:
- 生成器通过
yield返回数据,每次执行到yield会暂停; - 支持用
next()手动控制迭代; - 使用
yield from可简化嵌套生成器; - 在大文件读取、流式数据处理等场景下表现突出;
- 是节省内存、提升性能的优雅解决方案。
掌握生成器后,你可以轻松编写高效的数据管道,实现更灵活的程序逻辑。