Python3 迭代器与生成器详解
在 Python3 中,迭代器(Iterator)和生成器(Generator)是实现高效循环和数据流处理的核心机制。它们允许程序以惰性(Lazy)方式逐个生成值,而非一次性构建完整数据结构,从而显著提升内存效率和代码可读性。以下从多个维度详细解析迭代器与生成器的核心概念、实现原理及应用场景:
一、迭代器(Iterator)
1. 迭代器协议
- 可迭代对象(Iterable):实现了
__iter__()方法的对象(如列表、字典、字符串)。 - 迭代器(Iterator):实现了
__iter__()和__next__()方法的对象。__iter__():返回迭代器自身。__next__():返回下一个值,若没有值则抛出StopIteration异常。
2. 手动实现迭代器
class Counter:
def __init__(self, max_value):
self.current = 0
self.max = max_value
def __iter__(self):
return self # 返回迭代器自身
def __next__(self):
if self.current < self.max:
value = self.current
self.current += 1
return value
else:
raise StopIteration # 终止迭代
# 使用迭代器
counter = Counter(3)
print(next(counter)) # 输出: 0
print(next(counter)) # 输出: 1
print(next(counter)) # 输出: 2
print(next(counter)) # 抛出StopIteration
3. 迭代器的应用场景
- 遍历大型数据集:无需加载整个数据集到内存。
- 自定义遍历逻辑:如树形结构的深度优先遍历。
二、生成器(Generator)
1. 生成器函数
- 使用
yield关键字的函数,每次调用next()时暂停执行并返回值。
def counter(max_value):
current = 0
while current < max_value:
yield current # 暂停执行并返回值
current += 1
# 使用生成器
gen = counter(3)
print(next(gen)) # 输出: 0
print(next(gen)) # 输出: 1
print(next(gen)) # 输出: 2
print(next(gen)) # 抛出StopIteration
2. 生成器表达式
- 类似列表推导式,但使用圆括号
()。
gen = (x**2 for x in range(3)) # 生成器表达式
print(next(gen)) # 输出: 0
print(next(gen)) # 输出: 1
print(next(gen)) # 输出: 4
3. 生成器的状态管理
- 生成器保存执行状态,每次
next()恢复执行:
def gen_example():
print("开始执行")
yield 1
print("继续执行")
yield 2
print("结束执行")
g = gen_example()
next(g) # 输出: 开始执行 → 1
next(g) # 输出: 继续执行 → 2
next(g) # 输出: 结束执行 → StopIteration
三、迭代器与生成器的对比
| 特性 | 迭代器 | 生成器 |
|---|---|---|
| 实现方式 | 类 + __iter__()和__next__() |
函数 + yield或生成器表达式 |
| 状态管理 | 需手动维护内部状态 | 自动保存函数执行状态 |
| 代码复杂度 | 较高(需实现双方法) | 较低(结构简洁) |
| 内存效率 | 高(惰性生成值) | 更高(无需显式维护状态) |
四、生成器的高级特性
1. 生成器的 send () 方法
- 向生成器内部发送值并恢复执行。
def receiver():
while True:
item = yield # 接收外部发送的值
print(f"收到: {item}")
r = receiver()
next(r) # 启动生成器
r.send("消息1") # 输出: 收到: 消息1
r.send("消息2") # 输出: 收到: 消息2
2. 生成器的 throw () 和 close ()
throw():向生成器抛出异常。close():终止生成器。
def gen():
try:
yield 1
yield 2
except ValueError:
print("处理异常")
g = gen()
print(next(g)) # 输出: 1
g.throw(ValueError) # 输出: 处理异常
g.close() # 关闭生成器
next(g) # 抛出StopIteration
五、应用场景
1. 大数据处理
- 示例:处理 GB 级日志文件。
def read_large_file(file_path):
with open(file_path) as f:
for line in f: # 文件对象是迭代器,逐行读取
yield line
# 处理日志
for line in read_large_file("huge_log.txt"):
process(line) # 逐行处理,不加载整个文件
2. 无限序列
- 示例:生成斐波那契数列。
def fibonacci():
a, b = 0, 1
while True:
yield a
a, b = b, a + b
fib = fibonacci()
print(next(fib)) # 输出: 0
print(next(fib)) # 输出: 1
print(next(fib)) # 输出: 1
3. 管道处理
- 示例:数据过滤与转换流水线。
def source():
for i in range(10):
yield i
def filter_even(nums):
for num in nums:
if num % 2 == 0:
yield num
def multiply_by_10(nums):
for num in nums:
yield num * 10
# 组合管道
pipeline = multiply_by_10(filter_even(source()))
for result in pipeline:
print(result) # 输出: 0, 20, 40, 60, 80
六、性能优化
1. 内存占用对比
- 列表推导式:一次性生成所有值,占用 O (n) 内存。
- 生成器表达式:惰性生成值,占用 O (1) 内存。
# 列表推导式(占用大量内存)
squares_list = [x**2 for x in range(10**6)]
# 生成器表达式(内存高效)
squares_gen = (x**2 for x in range(10**6))
2. 时间效率
- 生成器在处理大规模数据时通常更快,因为避免了频繁的内存分配和复制。
七、常见问题与注意事项
-
生成器只能遍历一次
生成器耗尽后无法重置,需重新创建。gen = (x for x in range(3)) list(gen) # 输出: [0, 1, 2] list(gen) # 输出: [](已耗尽) -
避免过度嵌套生成器
复杂逻辑可拆分为多个生成器函数,保持代码可读性。
总结
- 迭代器是实现了迭代器协议的对象,手动管理状态。
- 生成器是更高级的迭代器,通过
yield自动管理状态,代码更简洁。 - 生成器表达式提供轻量级语法,适合简单场景。
- 两者均支持惰性求值,显著提升内存效率,尤其适合大数据处理。
合理使用迭代器和生成器,可使 Python 代码更高效、更具表达力。
浙公网安备 33010602011771号