29、Python 迭代器与可迭代对象原理:从协议实现到高阶应用

Python 迭代器与可迭代对象原理:从协议实现到高阶应用

一、深入理解迭代机制

1.1 迭代器协议核心

Python的迭代机制建立在__iter____next__双方法协议之上,其运作原理如下:

class MyRangeIterator:
    def __init__(self, start, end):
        self.current = start
        self.end = end

    def __iter__(self):
        return self

    def __next__(self):
        if self.current >= self.end:
            raise StopIteration
        value = self.current
        self.current += 1
        return value

代码解析:

  • __iter__返回迭代器自身,符合迭代器协议
  • __next__实现核心逻辑,控制迭代终止条件
  • StopIteration异常是迭代终止的标准信号

注意事项:

  • 迭代器只能单向前进,不可重置
  • 同一个迭代器实例无法被多个循环共享
  • 迭代结束后再次调用next()会持续抛出StopIteration

1.2 可迭代对象本质

可迭代对象与迭代器的关键区别在于:

特性可迭代对象迭代器
实现方法仅需__iter__需要__iter__和__next__
状态保持无状态维护迭代状态
复用性可多次迭代单次耗尽
内存占用可能较大通常较小

典型可迭代对象实现:

class MyRangeIterable:
    def __init__(self, start, end):
        self.start = start
        self.end = end

    def __iter__(self):
        return MyRangeIterator(self.start, self.end)

二、惰性计算实践

2.1 自定义高效生成器

实现支持步长的惰性生成器:

class AdvancedRange:
    def __init__(self, start, end=None, step=1):
        if end is None:
            start, end = 0, start
        self.start = start
        self.end = end
        self.step = step

    def __iter__(self):
        current = self.start
        while current < self.end:
            yield current
            current += self.step

# 使用示例
for num in AdvancedRange(1, 1000000, 2):
    if num > 100:
        break  # 实际仅生成到101即终止

核心优势:

  • 首先生成算法复杂度为O(1)
  • 内存占用恒定,与范围大小无关
  • 支持提前终止迭代,避免无效计算

2.2 生成器表达式

Python提供更简洁的生成器语法:

# 生成器表达式
cubes = (x**3 for x in range(10**6) 

# 等效的生成器函数
def generate_cubes():
    for x in range(10**6):
        yield x**3

最佳实践:

  • 数据量 > 1MB时优先使用生成器
  • 多次遍历需求应转换为容器类型
  • 注意生成器的单次消费特性

三、itertools模块高阶应用

3.1 无限迭代器妙用

import itertools

# 无限ID生成器
def id_generator(prefix):
    counter = itertools.count(1)
    while True:
        yield f"{prefix}{next(counter)}"

# 应用示例
user_gen = id_generator("USER_")
print(next(user_gen))  # USER_1
print(next(user_gen))  # USER_2

3.2 迭代器组合技

# 多级数据处理管道
def data_pipeline():
    # 阶段1:数据生成
    raw_data = itertools.islice(itertools.count(), 1000)
    
    # 阶段2:数据过滤
    filtered = filter(lambda x: x % 3 == 0, raw_data)
    
    # 阶段3:数据转换
    transformed = map(lambda x: x**2, filtered)
    
    # 阶段4:结果分块
    return iter(lambda: list(itertools.islice(transformed, 10)), [])

# 分批获取处理结果
batch_gen = data_pipeline()
for _ in range(3):
    print(next(batch_gen))  # 每次输出10个元素

四、内存优化与性能测试

4.1 内存占用对比

import sys

# 列表推导式
list_data = [x for x in range(10**6)]
print(sys.getsizeof(list_data))  # 约8.4MB

# 生成器
gen_data = (x for x in range(10**6))
print(sys.getsizeof(gen_data))  # 约128B

4.2 性能基准测试

使用timeit模块进行性能分析:

import timeit

# 列表处理
list_time = timeit.timeit(
    'sum([x**2 for x in range(100000)])', 
    number=100
)

# 生成器处理
gen_time = timeit.timeit(
    'sum((x**2 for x in range(100000)))', 
    number=100
)

print(f"List time: {list_time:.3f}s")
print(f"Generator time: {gen_time:.3f}s")

典型结果:

  • 小数据量(<1k):列表更快
  • 大数据量(>10k):生成器优势明显
  • 内存受限场景:生成器唯一选择

五、企业级应用实践

5.1 数据库流式读取

import psycopg2
from itertools import islice

class DatabaseStream:
    def __init__(self, query, batch_size=1000):
        self.conn = psycopg2.connect(...)
        self.cursor = self.conn.cursor()
        self.cursor.execute(query)
        self.batch_size = batch_size

    def __iter__(self):
        while True:
            rows = self.cursor.fetchmany(self.batch_size)
            if not rows:
                self.conn.close()
                return
            yield from rows

# 使用示例
stream = DatabaseStream("SELECT * FROM billion_row_table")
for row in islice(stream, 10000):
    process_row(row)  # 仅加载处理所需数据

5.2 异步迭代器

Python 3.6+支持异步迭代协议:

import aiohttp

class AsyncWebCrawler:
    def __init__(self, urls):
        self.urls = urls

    def __aiter__(self):
        self.index = 0
        return self

    async def __anext__(self):
        if self.index >= len(self.urls):
            raise StopAsyncIteration
        async with aiohttp.ClientSession() as session:
            async with session.get(self.urls[self.index]) as response:
                result = await response.text()
                self.index += 1
                return result

# 使用示例
async for content in AsyncWebCrawler(url_list):
    parse_content(content)

六、深度练习题

6.1 无限斐波那契迭代器

class FibonacciInfinity:
    def __init__(self):
        self.a, self.b = 0, 1

    def __iter__(self):
        return self

    def __next__(self):
        value = self.a
        self.a, self.b = self.b, self.a + self.b
        return value

# 验证实现
fib = FibonacciInfinity()
print([next(fib) for _ in range(10)])  # [0,1,1,2,3,5,8,13,21,34]

6.2 迭代器适配器

实现类似RxJS的观察者模式:

class IteratorAdapter:
    def __init__(self, iterable):
        self.iterator = iter(iterable)
        self.subscribers = []

    def subscribe(self, callback):
        self.subscribers.append(callback)

    def __iter__(self):
        for item in self.iterator:
            for callback in self.subscribers:
                callback(item)
            yield item

# 使用示例
adapter = IteratorAdapter(range(5))
adapter.subscribe(lambda x: print(f"Log: {x}"))
adapter.subscribe(lambda x: print(f"Double: {x*2}"))

list(adapter)  # 触发所有回调

结语

掌握迭代器协议是成为Python高级开发者的必经之路。本文从基础实现到企业级应用,揭示了迭代器在数据处理、内存优化和异步编程中的核心价值。建议读者通过实现自定义迭代器、优化现有代码中的迭代逻辑来深化理解。记住:好的迭代器设计能让程序既优雅又高效!

扩展阅读方向:

  • 生成器协程(yield from语法)
  • 迭代器模式在设计模式中的应用
  • PEP 525 异步生成器规范
  • 函数式编程中的惰性求值
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wolf犭良

谢谢您的阅读与鼓励!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值