Python3 迭代器与生成器

Python迭代器与生成器详解

Python迭代器与生成器详解

专为编程小白准备的通俗易懂指南,通过生活化比喻和代码示例掌握迭代器与生成器核心概念

迭代器 (Iterator)

生活比喻

迭代器就像自助餐厅的取餐流水线 – 你拿着餐盘依次经过各个菜品区,每次只能取一道菜,吃完才能取下一道。你不需要知道整个菜单,只需关注当前的菜品。

什么是迭代器?

迭代器是一个可以记住遍历位置的对象,它有两个基本方法:

  • __iter__(): 返回迭代器对象本身
  • __next__(): 返回容器中的下一个元素

为什么要使用迭代器?

  • 不需要一次性加载所有数据到内存(节省内存)
  • 提供统一的遍历接口(字符串、列表、字典等都可用)
  • 支持惰性计算(需要时才生成数据)

优点

  • 内存效率高(一次只处理一个元素)
  • 通用遍历接口
  • 支持无限序列

缺点

  • 无法随机访问元素
  • 只能向前遍历,不能后退
  • 使用后元素消失(单向)

创建迭代器

# 自定义迭代器示例
class CountDown:
    def __init__(self, start):
        self.current = start

    def __iter__(self):
        return self

    def __next__(self):
        if self.current <= 0:
            raise StopIteration
        else:
            num = self.current
            self.current -= 1
            return num

# 使用迭代器
counter = CountDown(5)
for num in counter:
    print(num) # 输出: 5, 4, 3, 2, 1

使用内置函数

# 将列表转换为迭代器
my_list = [1, 2, 3]
my_iter = iter(my_list)

print(next(my_iter)) # 输出: 1
print(next(my_iter)) # 输出: 2
print(next(my_iter)) # 输出: 3
# print(next(my_iter)) # 再次调用会引发StopIteration异常

生成器 (Generator)

生活比喻

生成器就像自动售货机 – 你按一下按钮(调用next()),它就出来一件商品(生成一个值)。它不需要一次性准备所有商品,而是按需生产。

什么是生成器?

生成器是一种特殊类型的迭代器,创建更简单:

  • 使用 yield 关键字
  • 不需要定义 __iter__() 和 __next__() 方法
  • 自动实现迭代器协议

生成器的两种创建方式

  1. 生成器函数:使用def定义,包含yield语句
  2. 生成器表达式:类似列表推导式,使用圆括号

优点

  • 代码更简洁(自动实现迭代器协议)
  • 状态自动保存(局部变量自动保存)
  • 更高效的内存使用
  • 支持管道式数据处理

缺点

  • 只能迭代一次
  • 没有长度属性
  • 调试相对复杂

生成器函数示例

# 生成斐波那契数列
def fibonacci(max_num):
    a, b = 0, 1
    while a < max_num:
        yield a # 暂停函数,返回a的值
        a, b = b, a + b

# 使用生成器
for num in fibonacci(100):
    print(num, end=’ ‘)
# 输出: 0 1 1 2 3 5 8 13 21 34 55 89

生成器表达式示例

# 列表推导式:一次性生成所有元素
squares_list = [x*x for x in range(10)]

# 生成器表达式:按需生成元素
squares_gen = (x*x for x in range(10))

print(squares_list) # 输出: [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
print(squares_gen) # 输出: <generator object <genexpr> at 0x…>

# 使用生成器
for square in squares_gen:
    print(square, end=’ ‘)
# 输出: 0 1 4 9 16 25 36 49 64 81

yield 关键字的高级用法

# 双向通信生成器
def interactive_gen():
    name = yield “What’s your name?”
    age = yield f”Hello {name}! How old are you?”
    yield f”Wow, {age} is a great age!”

gen = interactive_gen()
print(next(gen)) # 输出: What’s your name?
print(gen.send(“Alice”)) # 输出: Hello Alice! How old are you?
print(gen.send(30)) # 输出: Wow, 30 is a great age!

迭代器 vs 生成器

生活比喻

迭代器是工厂的传送带(需要专门设计),生成器是自动售货机(一键生成)。生成器是迭代器的”语法糖”(更简单的写法)。

核心区别

特性 迭代器 生成器
定义方式 类(实现__iter__和__next__) 函数(使用yield)或生成器表达式
内存使用 低(但取决于实现) 极低(每次只生成一个值)
代码复杂度 较高(需要实现两个方法) 较低(自动实现协议)
状态保存 手动保存 自动保存(局部冻结)
使用场景 需要精确控制迭代过程 快速创建迭代器,处理大数据流

如何选择?

使用迭代器当:

  • 需要设计复杂的状态管理
  • 需要实现额外的迭代控制方法
  • 需要在多个地方复用相同的迭代逻辑

使用生成器当:

  • 快速实现简单迭代需求
  • 处理大型数据流(文件、网络流)
  • 需要节省内存的场景
  • 实现管道式数据处理

实际应用场景

  • 文件读取:逐行读取大文件而不耗尽内存
  • 流式数据处理:处理网络数据流
  • 无限序列:斐波那契数列、素数生成
  • 管道处理:多个处理步骤串联
# 读取大文件的生成器应用
def read_large_file(file_path):
    with open(file_path, ‘r’, encoding=’utf-8′) as file:
        for line in file:
            yield line.strip()

# 使用生成器处理10GB文件只需少量内存
for line in read_large_file(‘huge_log_file.txt’):
    if ‘ERROR’ in line:
        print(line)

© 2023 Python迭代器与生成器学习指南 | 编码小白友好的知识总结

记住:生成器是迭代器的简化版,两者都是处理大数据流和节省内存的利器

发表评论

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

滚动至顶部