Python迭代器与生成器:优雅的惰性计算艺术

一、迭代器协议:__iter____next__的魔法

迭代器的本质

Python中的迭代器不是存储所有元素的容器,而是惰性计算的协议实现。核心在于两个方法:

  • __iter__():返回迭代器自身
  • __next__():返回下一个元素,耗尽时抛出StopIteration
python 复制代码
class CountDown:
    """自定义迭代器:倒计时"""
    def __init__(self, start):
        self.current = start
    
    def __iter__(self):
        return self  # 迭代器必须返回自身
    
    def __next__(self):
        if self.current <= 0:
            raise StopIteration
        num = self.current
        self.current -= 1
        return num

# 使用
for num in CountDown(5):
    print(num)  # 输出: 5 4 3 2 1

迭代器的优势

  • 内存高效:不一次性加载所有数据
  • 无限序列:可以表示无限长的序列
  • 通用接口 :统一的for循环处理方式

二、生成器:yield的暂停与恢复魔法

生成器函数

生成器是创建迭代器的语法糖 ,使用yield暂停函数执行并返回值:

python 复制代码
def fibonacci_generator(limit):
    """生成斐波那契数列"""
    a, b = 0, 1
    count = 0
    while count < limit:
        yield a  # 暂停执行,返回a
        a, b = b, a + b
        count += 1

# 生成器对象
fib_gen = fibonacci_generator(10)
print(next(fib_gen))  # 0
print(next(fib_gen))  # 1
print(list(fib_gen))  # [1, 2, 3, 5, 8, 13, 21, 34]

生成器表达式

更简洁的生成器创建方式:

python 复制代码
# 传统列表推导(立即计算)
squares_list = [x**2 for x in range(1000000)]  # 占用大量内存

# 生成器表达式(惰性计算)
squares_gen = (x**2 for x in range(1000000))  # 几乎不占内存
print(next(squares_gen))  # 0
print(next(squares_gen))  # 1

三、yield from:生成器的委派机制

简化嵌套生成器

python 复制代码
def chain_generators(*iterables):
    """连接多个可迭代对象"""
    for iterable in iterables:
        yield from iterable  # 委派给子生成器

# 等效于:
# for item in iterable:
#     yield item

result = list(chain_generators([1, 2], 'ab', (True, False)))
# [1, 2, 'a', 'b', True, False]

四、生成器的高级用法

1. 协程:双向通信

python 复制代码
def coroutine_generator():
    """接收外部数据的生成器"""
    total = 0
    while True:
        value = yield total  # 暂停并接收发送的值
        if value is None:
            break
        total += value

coro = coroutine_generator()
next(coro)  # 启动生成器(预激)
print(coro.send(10))  # 10
print(coro.send(20))  # 30
coro.close()  # 关闭生成器

2. 上下文管理

python 复制代码
from contextlib import contextmanager

@contextmanager
def managed_resource():
    """生成器实现的上下文管理器"""
    print("获取资源")
    resource = "资源对象"
    try:
        yield resource
    finally:
        print("释放资源")

with managed_resource() as r:
    print(f"使用 {r}")

五、性能对比:迭代器 vs 列表

python 复制代码
import time
import sys

def test_memory_usage():
    """内存使用对比"""
    # 列表:一次性加载所有数据
    list_data = [i for i in range(1000000)]
    print(f"列表内存: {sys.getsizeof(list_data):,} bytes")
    
    # 生成器:惰性计算
    gen_data = (i for i in range(1000000))
    print(f"生成器内存: {sys.getsizeof(gen_data):,} bytes")

def test_performance():
    """性能对比"""
    n = 10_000_000
    
    # 列表推导
    start = time.time()
    _ = [x**2 for x in range(n)]
    list_time = time.time() - start
    
    # 生成器表达式
    start = time.time()
    _ = (x**2 for x in range(n))
    gen_time = time.time() - start
    
    print(f"列表推导: {list_time:.3f}s")
    print(f"生成器表达式: {gen_time:.3f}s")

test_memory_usage()
test_performance()

六、实用模式与陷阱

1. 生成器的一次性使用

python 复制代码
gen = (x for x in range(3))
print(list(gen))  # [0, 1, 2]
print(list(gen))  # [] !已耗尽

2. itertools模块的迭代器工具

python 复制代码
from itertools import islice, count, cycle

# 无限序列的切片
first_10 = list(islice(count(10), 5))  # [10, 11, 12, 13, 14]

# 循环迭代器
cycler = cycle('ABC')
print([next(cycler) for _ in range(6)])  # ['A', 'B', 'C', 'A', 'B', 'C']

3. 自定义可迭代对象

python 复制代码
class BatchProcessor:
    """分批处理大数据集"""
    def __init__(self, data, batch_size):
        self.data = data
        self.batch_size = batch_size
    
    def __iter__(self):
        """返回生成器迭代器"""
        for i in range(0, len(self.data), self.batch_size):
            yield self.data[i:i + self.batch_size]

data = list(range(100))
batcher = BatchProcessor(data, 10)
for batch in batcher:
    process(batch)  # 每次处理10个元素

总结

迭代器和生成器是Python惰性计算哲学的体现,它们通过:

  1. 按需计算节省内存
  2. 统一的迭代协议简化API设计
  3. 生成器协程实现复杂控制流
  4. 优雅的语法让代码更清晰
相关推荐
老百姓懂点AI1 天前
[RAG实战] 向量数据库选型与优化:智能体来了(西南总部)AI agent指挥官的长短期记忆架构设计
python
喵手1 天前
Python爬虫零基础入门【第九章:实战项目教学·第15节】搜索页采集:关键词队列 + 结果去重 + 反爬友好策略!
爬虫·python·爬虫实战·python爬虫工程化实战·零基础python爬虫教学·搜索页采集·关键词队列
Suchadar1 天前
if判断语句——Python
开发语言·python
ʚB҉L҉A҉C҉K҉.҉基҉德҉^҉大1 天前
自动化机器学习(AutoML)库TPOT使用指南
jvm·数据库·python
喵手1 天前
Python爬虫零基础入门【第九章:实战项目教学·第14节】表格型页面采集:多列、多行、跨页(通用表格解析)!
爬虫·python·python爬虫实战·python爬虫工程化实战·python爬虫零基础入门·表格型页面采集·通用表格解析
0思必得01 天前
[Web自动化] 爬虫之API请求
前端·爬虫·python·selenium·自动化
莫问前路漫漫1 天前
WinMerge v2.16.41 中文绿色版深度解析:文件对比与合并的全能工具
java·开发语言·python·jdk·ai编程
木头左1 天前
Backtrader框架下的指数期权备兑策略资金管理实现与风险控制
python
玄同7651 天前
LangChain 核心组件全解析:构建大模型应用的 “乐高积木”
人工智能·python·语言模型·langchain·llm·nlp·知识图谱
喵手1 天前
Python爬虫实战:从零构建 Hacker News 数据采集系统:API vs 爬虫的技术抉择!(附CSV导出 + SQLite 存储)!
爬虫·python·爬虫实战·hacker news·python爬虫工程化实战·零基础python爬虫教学·csv导出