Python基础-day8:迭代器和生成器的区别及其各自实现方式和使用场景

1. 迭代器

        迭代器提供了一种惰性(lazy evaluation)获取数据的方法,使得我们能够逐步访问序列中的元素,而无需一次性加载所有数据。其主要优点包括节省内存、提高性能、支持自定义遍历逻辑等。

1.1 实现协议
  • __iter__():返回自身。
  • __next__():返回下一个元素;如果没有更多元素,则抛出 StopIteration 异常。

注意:

        可迭代对象(Iterable)与迭代器不同:

  • 可迭代对象实现 __iter__() 方法,返回一个迭代器。
  • 迭代器既实现 __iter__() 又实现 __next__()
1.2 迭代器的创建
class MyRange:
    def __init__(self, stop):
        self.stop = stop
        self.current = 0

    def __iter__(self):
        return self  # 返回自身作为迭代器

    def __next__(self):
        if self.current < self.stop:
            value = self.current
            self.current += 1
            return value
        else:
            raise StopIteration  # 结束迭代

# 使用示例
for num in MyRange(3):
    print(num)  # 输出: 0, 1, 2
1.3 可复用迭代器和一次性迭代器
1.3.1 一次性迭代器(如内置 mapfilter、zip等
  • 当数据只需要被遍历一次时,比如在数据预处理阶段,对一系列数据进行某种转换(如使用map函数将列表中的每个元素都转换为平方数),一次性迭代器可以节省内存,因为它不需要保存额外的状态来支持多次从头遍历。
  • 处理流式数据,例如从网络套接字或文件中逐行读取数据,每一行数据处理完就不再需要回头重新处理,使用一次性迭代器可以简化处理流程。
data = [1, 2, 3]
square_iter = map(lambda x: x**2, data)

print(list(square_iter))  # 输出: [1, 4, 9]
print(list(square_iter))  # 输出: [](已耗尽)
1.3.2 可复用迭代器(通过 __iter__ 返回新实例)
  • 在需要多次遍历相同数据的算法中,比如排序算法中,可能需要多次比较和遍历数据来确定最终的顺序,可复用迭代器就可以避免重复创建迭代器的开销。
  • 当需要在不同的处理步骤中对同一组数据进行操作时,可复用迭代器可以方便地在不同步骤之间共享和使用数据,而无需重新构建迭代器。
class ReusableRange:
    def __init__(self, stop):
        self.stop = stop

    def __iter__(self):
        return MyRange(self.stop)  # 每次返回新的迭代器实例

class MyRange:
    def __init__(self, stop):
        self.stop = stop
        self.current = 0
    # __next__ 方法同上...

r = ReusableRange(3)
print(list(r))  # 输出: [0, 1, 2]
print(list(r))  # 可再次使用,输出: [0, 1, 2]

2. 生成器

        生成器是一种特殊的迭代器,通过函数定义,用 yield 语句生成值。生成器可以自动实现迭代协议,无需手动实现 __iter__()__next__()

2.1 表达式

yield:暂停函数执行并返回值,保留函数的状态,以便下一次继续执行。

def my_range(stop):
    current = 0
    while current < stop:
        yield current  # 暂停执行并返回值
        current += 1

# 使用示例
for num in my_range(3):
    print(num)  # 输出: 0, 1, 2

简洁写法:

gen = (x**2 for x in range(3))  # 创建生成器
print(next(gen))  # 输出: 0
print(next(gen))  # 输出: 1

3. 直观化展现

对比维度 迭代器(Iterator) 生成器(Generator)
定义本质 实现 __iter__() + __next__() 方法的对象 使用 yield 关键字的函数 / 表达式(生成器函数 / 生成器表达式)
状态管理 手动维护状态(如计数器、指针等,通过类属性记录) 自动维护状态(暂停 / 恢复执行,依托 Python 解释器内部机制)
语法复杂度 较高(需编写类,实现双魔法方法) 较低(类似普通函数,用 yield 替代 return 即可)
内存效率 若逻辑不当,可能一次性加载大量数据(如直接返回列表全部元素) 惰性计算(按需生成,逐个产出结果,内存占用稳定)
实现方式

类 + __iter__()/__next__()(需显式抛出 StopIteration

生成器函数(yield 关键字)或生成器表达式((x for x in ...)
典型应用场景 遍历自定义容器(如树、图结构,需精细控制遍历逻辑) 处理大文件 / 无限流(如逐行读 GB 级文件、生成无限序列)、简化复杂迭代逻辑
核心语法差异 依赖类与魔法方法实现迭代协议 依赖 yield 关键字实现 “暂停 - 恢复” 机制
性能与使用偏好 适合需深度定制迭代逻辑的场景,但代码冗余 优先推荐!内存友好、语法简洁,覆盖 80%+ 迭代场景,仅复杂容器遍历需迭代器补位

4. 一句话总结

        迭代器是 “硬核自定义工具”,适合精细控制容器遍历;生成器是 “高效懒人神器”,用极简语法实现惰性迭代,日常开发优先选生成器,复杂场景再用迭代器兜底 。

你可能感兴趣的:(Python基础-day8:迭代器和生成器的区别及其各自实现方式和使用场景)