文章目录
一、前言
在 Python 中,生成器(Generator)是一种特殊的迭代器,通过 yield 关键字生成值,具备惰性求值特性。这意味着生成器在每次迭代时计算下一个值,而不是一次性生成所有值。与普通列表相比,生成器更节省内存,适合处理大数据流或无限序列。
二、生成器的定义与使用
1. 使用 yield 关键字创建生成器
在 Python 中,生成器本质上是带有 yield 语句的函数。当函数包含 yield 时,每次调用生成器的 next() 方法时,函数会从上次暂停的地方继续执行。
✅ 示例:生成 Fibonacci 序列
def fibonacci(n):
"""生成 n 个 Fibonacci 数列"""
a, b = 0, 1
for _ in range(n):
yield a
a, b = b, a + b
# 使用生成器
gen = fibonacci(5)
# 逐个获取生成器中的值
print(next(gen)) # 0
print(next(gen)) # 1
print(next(gen)) # 1
print(next(gen)) # 2
print(next(gen)) # 3
解释:
yield会将当前值返回,并在当前位置暂停。- 下次调用
next()时,从暂停位置继续执行。 - 生成器不会立即计算所有值,仅在迭代时生成数据,节省内存。
✅ yield 与 return 区别
return:终止函数并返回值。yield:在暂停位置保存状态,并返回当前值。
示例:
def example_return():
return 1
return 2 # 不会被执行
def example_yield():
yield 1
yield 2 # 可以多次返回
print(list(example_return())) # [1]
print(list(example_yield())) # [1, 2]
三、生成器表达式与列表解析
Python 提供了一种简洁的生成器表达式语法,类似于列表解析,但使用 () 而不是 []。
✅ 列表解析与生成器表达式对比
# 列表解析:一次性生成所有元素
lst = [x**2 for x in range(5)]
print(lst) # [0, 1, 4, 9, 16]
# 生成器表达式:按需生成元素
gen = (x**2 for x in range(5))
print(gen) # <generator object>
print(list(gen)) # [0, 1, 4, 9, 16]
区别:
- 列表解析会立即生成所有元素,占用内存。
- 生成器表达式惰性求值,按需生成元素,节省内存。
四、生成器方法:next() 和 send()
1. next() 方法
next()用于从生成器中获取下一个元素。- 如果元素耗尽,则抛出
StopIteration异常。
✅ 示例:
def counter():
n = 0
while n < 3:
yield n
n += 1
gen = counter()
print(next(gen)) # 0
print(next(gen)) # 1
print(next(gen)) # 2
# print(next(gen)) # 抛出 StopIteration 异常
2. send() 方法
send(value)可向生成器发送值,并将其赋给yield表达式。- 与
next()不同,send()可以与生成器交互,传递外部值。
✅ 示例:
def gen():
x = 0
while True:
x = yield x
print(f"Received: {x}")
g = gen()
print(next(g)) # 初始化生成器:0
print(g.send(10)) # Received: 10 → 返回 10
print(g.send(20)) # Received: 20 → 返回 20
五、生成器提高性能与应用
1. 节省内存
生成器适合处理大数据集或无限序列,因为它们不会将数据全部存入内存。
✅ 示例:生成百万整数
import sys
# 列表方式
lst = [i for i in range(10**6)]
print(f"List占用内存: {sys.getsizeof(lst)} 字节")
# 生成器方式
gen = (i for i in range(10**6))
print(f"Generator占用内存: {sys.getsizeof(gen)} 字节")
输出:
List占用内存: 8697464 字节
Generator占用内存: 112 字节
生成器显著减少了内存占用。
2. 文件读取处理
生成器可以高效地逐行读取大文件,避免一次性将数据加载到内存中。
✅ 示例:
def read_large_file(file_path):
with open(file_path, 'r') as f:
for line in f:
yield line.strip()
# 使用生成器逐行读取
for line in read_large_file('large_file.txt'):
print(line)
六、生成器使用案例
1. 无限序列生成
生成器可以创建无限序列,而不会耗尽内存。
✅ 示例:生成无限斐波那契数列
def infinite_fib():
a, b = 0, 1
while True:
yield a
a, b = b, a + b
# 无限生成斐波那契数列
fib = infinite_fib()
for _ in range(10):
print(next(fib), end=" ") # 0 1 1 2 3 5 8 13 21 34
2. 并行任务调度
生成器可用于协程,实现简易的任务调度。
✅ 示例:
import time
def task1():
for i in range(3):
print(f"Task 1 - {i}")
yield
time.sleep(1)
def task2():
for i in range(3):
print(f"Task 2 - {i}")
yield
time.sleep(1)
# 并行执行任务
t1 = task1()
t2 = task2()
for _ in range(3):
next(t1)
next(t2)
七、总结
- 生成器通过
yield实现惰性求值,按需生成数据,节省内存。 - 与
return不同,yield会在暂停位置恢复执行。 - 使用
send()方法可与生成器进行双向通信。 - 生成器适合处理大数据、流数据或无限序列,显著提高程序性能。
1735

被折叠的 条评论
为什么被折叠?



