Python 中的迭代器模式(Iterator Pattern)
迭代器模式是一种行为型设计模式,其核心目的是:
提供一种方法顺序访问一个聚合对象(容器)中的各个元素,而又无需暴露该对象的内部表示。
形象比喻:就像翻书——你只需要调用“下一页”操作,就能依次阅读内容,而不需要知道书是怎么装订的、页码怎么存储的。
迭代器模式的优点
- 分离遍历行为与容器:容器只负责存储数据,迭代器负责遍历
- 支持多种遍历方式(正向、反向、过滤等)
- 符合单一职责原则:容器和迭代器各司其职
- 支持惰性加载:只在需要时获取下一个元素
Python 中的特殊之处
Python 语言内置了对迭代器模式的最完美支持,通过 迭代协议(Iteration Protocol) 实现:
- 任何实现了
__iter__()和__next__()方法的对象都是迭代器 - 任何实现了
__iter__()方法的对象都是可迭代对象(Iterable) for循环、list()、tuple()、sum()等都自动使用迭代器协议
因此,在 Python 中,迭代器模式几乎不需要手动实现,但理解其原理有助于写出更高效、更优雅的代码。
Python 内置迭代器示例
# 列表本身是可迭代对象(Iterable)
my_list = [1, 2, 3, 4]
# 获取其迭代器
it = iter(my_list) # 调用 my_list.__iter__()
print(next(it)) # 1 调用 it.__next__()
print(next(it)) # 2
print(next(it)) # 3
print(next(it)) # 4
# print(next(it)) # 抛出 StopIteration 异常,表示迭代结束
for 循环内部就是这样工作的:
for item in my_list:
print(item)
# 等价于:
it = iter(my_list)
while True:
try:
item = next(it)
print(item)
except StopIteration:
break
手动实现迭代器模式(经典方式)
class ReverseIterator:
"""反向迭代器"""
def __init__(self, data):
self.data = data
self.index = len(data) # 从末尾开始
def __iter__(self):
return self
def __next__(self):
if self.index == 0:
raise StopIteration
self.index -= 1
return self.data[self.index]
class MyCollection:
"""容器类"""
def __init__(self, items):
self.items = items
def __iter__(self):
return iter(self.items) # 正向迭代(使用内置)
def reverse_iter(self):
return ReverseIterator(self.items) # 提供反向迭代器
# 使用
collection = MyCollection([1, 2, 3, 4, 5])
print("正向遍历:")
for x in collection:
print(x)
print("\n反向遍历:")
for x in collection.reverse_iter():
print(x)
输出:
正向遍历:
1
2
3
4
5
反向遍历:
5
4
3
2
1
更 Pythonic 的方式:使用生成器(推荐!)
生成器是 Python 中实现迭代器的最简洁方式,使用 yield 关键字。
def reverse_generator(data):
"""生成器函数:反向遍历"""
for i in range(len(data)-1, -1, -1):
yield data[i]
def fibonacci_generator(n):
"""生成斐波那契数列(惰性计算)"""
a, b = 0, 1
for _ in range(n):
yield a
a, b = b, a + b
# 使用
data = [1, 2, 3, 4, 5]
print("反向生成器:")
for x in reverse_generator(data):
print(x)
print("\n斐波那契数列前 10 项:")
for num in fibonacci_generator(10):
print(num, end=" ")
# 输出:0 1 1 2 3 5 8 13 21 34
生成器自动实现了 __iter__() 和 __next__(),并且支持 StopIteration。
内置强大迭代工具:itertools 模块
Python 标准库 itertools 提供了大量高效的迭代器工具:
import itertools
data = [1, 2, 3]
# 无限循环
# for x in itertools.cycle(data): ...
# 重复元素
print(list(itertools.repeat(10, 3))) # [10, 10, 10]
# 累积
print(list(itertools.accumulate([1, 2, 3, 4]))) # [1, 3, 6, 10]
# 组合
print(list(itertools.combinations('ABC', 2))) # [('A', 'B'), ('A', 'C'), ('B', 'C')]
# 过滤
print(list(itertools.takewhile(lambda x: x < 5, [1, 4, 6, 7, 1]))) # [1, 4]
# 链式连接
print(list(itertools.chain('ABC', 'DEF'))) # ['A', 'B', 'C', 'D', 'E', 'F']
迭代器模式结构总结
| 角色 | Python 中的对应 |
|---|---|
| Iterator | 实现 __iter__() 和 __next__() 的对象 |
| ConcreteIterator | 自定义迭代器类或生成器 |
| Aggregate | 可迭代对象(实现 __iter__()) |
| ConcreteAggregate | list、tuple、dict、set、str 等 |
迭代器 vs 生成器 vs 可迭代对象
| 概念 | 是否可多次遍历 | 是否惰性计算 | 示例 |
|---|---|---|---|
| 可迭代对象 | 是 | 否 | list, tuple, str |
| 迭代器 | 否(一次用完) | 是 | iter(lst), 自定义迭代器 |
| 生成器 | 否 | 是 | yield 函数, (x for x in) |
Python 中的实际应用场景
- 文件读取:
for line in open('file.txt'):(惰性读取,不一次性加载) - 数据库查询:ORM 的查询集通常是惰性迭代器
- 数据流处理:处理大数据时避免内存爆炸
- 无限序列:如斐波那契、素数生成器
zip()、enumerate()、reversed()、sorted()等返回迭代器
最佳实践建议
- 优先使用生成器:写迭代器时,几乎总是用
yield而不是手动实现类 - 避免在循环中调用 list():除非真的需要全部数据,否则保持惰性
- 自定义容器时实现
__iter__():让它支持for循环 - 使用 itertools:解决 90% 的复杂遍历需求
# 推荐:惰性读取大文件
def read_large_file(file_path):
with open(file_path) as f:
for line in f: # 每次只读一行
yield line.strip()
总结
在 Python 中,迭代器模式不是“需要实现”的模式,而是语言核心特性。
掌握迭代协议和生成器,你就掌握了 Python 中最强大的数据处理工具之一。
如果你想看更高级的例子(如自定义可迭代容器、树结构遍历器、无限迭代器、协程与生成器的结合),或者如何用迭代器实现数据管道(Pipeline),欢迎继续问!