Python 迭代器模式

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__()
ConcreteAggregatelist、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),欢迎继续问!

文章已创建 3511

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

相关文章

开始在上面输入您的搜索词,然后按回车进行搜索。按ESC取消。

返回顶部