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. 时间效率

  • 生成器在处理大规模数据时通常更快,因为避免了频繁的内存分配和复制。

七、常见问题与注意事项

  1. 生成器只能遍历一次
    生成器耗尽后无法重置,需重新创建。
    gen = (x for x in range(3))
    list(gen)  # 输出: [0, 1, 2]
    list(gen)  # 输出: [](已耗尽)
    
  2. 避免过度嵌套生成器
    复杂逻辑可拆分为多个生成器函数,保持代码可读性。

总结

  • 迭代器是实现了迭代器协议的对象,手动管理状态。
  • 生成器是更高级的迭代器,通过yield自动管理状态,代码更简洁。
  • 生成器表达式提供轻量级语法,适合简单场景。
  • 两者均支持惰性求值,显著提升内存效率,尤其适合大数据处理。

合理使用迭代器和生成器,可使 Python 代码更高效、更具表达力。

posted on 2025-07-04 09:24  小陶coding  阅读(133)  评论(0)    收藏  举报