当前位置: 首页 > news >正文

迭代器和生成器

关于迭代器(Iterator)和生成器(Generator)的详细介绍和比较:

一、迭代器(Iterator)

1. 定义

  • 迭代器(Iterator) 是 Python 中用于遍历(或迭代)集合(如列表、元组、字典、集合等)元素的一种机制。
  • 它是一个可以记住遍历位置的对象,允许你逐个访问集合中的元素,而无需提前知道集合的大小。

2. 迭代器的特点

  • 惰性计算:迭代器不会一次性加载所有数据到内存,而是按需生成元素,适合处理大数据集。
  • 单向遍历:迭代器只能向前移动,不能回退或重置。
  • 只能遍历一次:遍历结束后,迭代器会耗尽,再次遍历需要重新创建。

3. 核心方法(每个迭代器必不可少的迭代器协议)

  • 要让一个类称为迭代器,必须实现__iter__()__next__()两种方法
  • __iter__():返回迭代器对象自身(self)(必须实现),在函数外创建迭代器可使用iter()
  • __next__():返回下一个元素,若没有元素则抛出 StopIteration 异常(必须实现)。在函数外使用迭代器调用next(),即可调用一次迭代器生成的元素。

4. 自定义迭代器示例

class MyIterator:def __init__(self, max_num):self.max_num = max_numself.current = 0def __iter__(self):return selfdef __next__(self):if self.current < self.max_num:self.current += 1return self.currentelse:raise StopIteration# 使用自定义的迭代器
it = MyIterator(3)
print(next(it))  # 1
print(next(it))  # 2

5. 特点

  • 内存高效、惰性计算:适合处理大型数据集(如文件逐行读取),因为迭代器不会一次性加载所有的数据,因此对内存的利用是高效的。

  • 单向性:只能向前遍历,不能回退或重置。

  • 无限序列:可以表示无限序列(如:itertools.count()

  • 逐行读取大文件的示例:

    with open("huge_file.txt") as file:for line in file:  # file 对象是迭代器,不会一次性加载全部内容print(line)
    

6.常见的迭代器工具

  • itertools 模块
    在Python中的itertools 模块提供了许多有用的迭代器

    import itertools# 无限迭代器
    count_iter = itertools.count(1)  # 1, 2, 3, ...
    cycle_iter = itertools.cycle("ABC")  # A, B, C, A, B, C, ...# 有限迭代器
    chain_iter = itertools.chain([1, 2], ["a", "b"])  # 1, 2, a, b
    
  • 包含yield的生成器
    生成器是一种特殊的迭代器

二、生成器(Generator)

1. 定义

  • 生成器是一种特殊的迭代器,他的数据是通过 yield 关键字动态生成实现的,而不是预先存储在内存中,具有惰性计算的特性。
  • 生成器函数在每次调用 next() 时执行到 yield 处暂停,保留当前状态,下次继续执行。
  • 生成器因为是迭代器的一种,因此也只能遍历依次,遍历结束后会跑出StopIteration

2. 实现方式

  • 生成器函数:使用 yield 关键字定义生成器函数。

    def count_up_to(n):num = 1while num <= n:yield num  # 每次调用 next() 时返回 num,并暂停num += 1# 创建生成器对象
    gen = count_up_to(3)
    print(next(gen))  # 1
    print(next(gen))  # 2
    print(next(gen))  # 3
    # print(next(gen))  # 抛出StopIteration异常,因为生成器已经遍历完
    
  • 生成器表达式:类似列表推导式,但使用圆括号 ()并返回生成器。

# 列表推导式(立即计算)
squares_list = [x ** 2 for x in range(3)]  # [0, 1, 4]# 生成器表达式(惰性计算)
squares_gen = (x ** 2 for x in range(3))
print(next(squares_gen))  # 0
print(next(squares_gen))  # 1

3. yield生成器的工作机制

  • 了解yield的执行流程
    • 调用生成器函数时,返回一个生成器对象(不立即执行代码)。
    • 首次调用 next() /send(None)时,执行到第一个 yield,返回其值并 暂停。
    • 再次调用 next() 时,从上次暂停的位置继续执行,直到下一个 yield。
    • 如果函数结束或遇到 return(表示函数结束),抛出 StopIteration异常错误。
  • 生成器的状态保存
    • 生成器会 记住局部变量和执行位置
    • 生成器不会记住上次生成了什么,因此可以用send()传入值,直接告诉生成器上次生成了什么
  • . yield from 的介绍
    • yield from 是 Python 3.3+ 引入的语法,用于简化生成器的嵌套调用,使生成器可以委托(delegate)给另一个生成器或可迭代对象。它的主要作用是:
      • 替代 for 循环 + yield,让代码更简洁。
        # 传统方式使用yield (手动迭代子生成器)
        def generator1():for i in range(3):yield i
        def generator2():for j in generator1():yield j  # 手动迭代 generator1for value in generator2():print(value)  # 输出 0, 1, 2# 使用 yield from(自动委托)
        # 使用yield from 会自动遍历 range(3),并逐个 yield 值,无需手动循环
        def generator1():yield from range(3)  # 自动迭代 range(3)for value in generator1():print(value)  # 输出 0, 1, 2
        

			# 使用 yield from 委托给另一个生成器def sub_generator():yield 1yield 2return "Done"  # 返回值可以通过 yield from 获取def main_generator():#  yield from 自动 `yield` `sub_generator` 的所有值。# 并且捕获 `sub_generator` 的 `return` 值(通过 `StopIteration.value` 获取)。result = yield from sub_generator()  # 委托给 sub_generatorprint(f"子生成器返回值: {result}")  # 输出 "Done"for value in main_generator():print(value)  # 输出 1, 2# 输出:12子生成器返回值: Done```- **自动处理 `StopIteration`**,并获取子生成器的返回值。```pythondef sub_generator():print("子生成器启动")x = yield "请发送一个值"print(f"子生成器收到: {x}")yield f"处理后的值: {x * 2}"def main_generator():result = yield from sub_generator()print(f"子生成器返回值: {result}")gen = main_generator()print(next(gen))       # 输出 "请发送一个值"(启动子生成器)print(gen.send(10))    # 发送 10,输出 "子生成器收到: 10",返回 "处理后的值: 20"输出:子生成器启动请发送一个值子生成器收到: 10处理后的值: 20

3. yield from 与普通 yield 的对比

特性yieldyield from
代码简洁性需要手动 for 循环迭代自动委托,无需手动迭代
返回值处理无法直接获取子生成器的返回值可以获取子生成器的 return
异常传递需要手动处理子生成器的异常自动传递异常

5. 示例:yield生成器可以串联,形成数据处理管道

# 生成偶数的生成器
def even_numbers(numbers):for num in numbers:if num % 2 == 0:yield num
# 将生成数字平方的生成器
def squared_numbers(numbers):for num in numbers:yield num ** 2# 组合生成器,生成偶数的平方
nums = range(10)
pipeline = squared_numbers(even_numbers(nums))
print(list(pipeline))  # [0, 4, 16, 36, 64]

6. 生成器表达式 vs 列表推导式

# 生成器表达式(惰性计算)
gen = (x**2 for x in range(10))  # 列表推导式(立即计算)
lst = [x**2 for x in range(10)]  

7. 特点

  • 简洁性:自动实现 __iter__()__next__(),无需手动编写类。
  • 状态保存:每次 yield 会保留局部变量和代码执行位置。
  • 一次性使用:遍历结束后无法重复使用。

三、迭代器 vs 生成器

特性迭代器生成器
定义(实现方法)需手动实现 __iter____next__通过 yield 自动实现迭代器协议
内存利用低(惰性计算)更低(更简洁、高效的实现)
代码复杂度较高(需编写类)低(函数 + yield
灵活性可自定义复杂逻辑适合简单迭代逻辑
应用场景需要复杂的迭代状态管理、精细控制迭代行为 ; 需要复用迭代器或添加额外方法。需要快速实现惰性计算; 处理流式数据(如文件读取、网络请求); 简化迭代逻辑(如无限序列)

迭代器和生成器都是处理大数据和流式数据的利器,根据场景灵活选择即可。

相关文章:

  • 【Linux】网络--传输层--TCP协议基础
  • Sparse VideoGen开源:完全无损,视频生成速度加速两倍,支持Wan 2.1、HunyuanVideo等
  • HarmonyOS NEXT~鸿蒙操作系统功耗优化特性深度解析
  • 【HarmonyOS 5应用架构详解】深入理解应用程序包与多Module设计机制
  • 5.26 面经整理 360共有云 golang
  • 鸿蒙OSUniApp 制作悬浮按钮与菜单组件#三方框架 #Uniapp
  • 鸿蒙OSUniApp 实现的日期选择器与时间选择器组件#三方框架 #Uniapp
  • 关于vue结合elementUI输入框回车刷新问题
  • 视频检测AI智能分析网关V4摄像头异常位移检测算法全场景智能防护方案
  • 分布式爬虫架构设计
  • window 显示驱动开发-呈现开销改进(二)
  • [IMX] 08.RTC 时钟
  • 大模型RL方向面试题90道
  • 第九届水动力学与能源电力系统国际学术会议(HEEPS 2025)
  • 告别延迟!modbus tcp转profine网关助力改造电厂改造升级
  • LeetCode#第58题:最后一个单词的长度
  • python打卡day37@浙大疏锦行
  • C/C++内存泄漏深度解析与系统化解决方案
  • uniapp 配置本地 https 开发环境(基于 Vue2 的 uniapp)
  • 【前端】使用HTTPS
  • 佛山格尔做网站的公司/邢台网站网页设计
  • wordpress 云主机/seo教程视频
  • 海沧网站建设/品牌关键词优化哪家便宜
  • 免费网站建设seo/如何优化网页加载速度
  • seo技术什么意思/新网站 seo
  • 东莞网站制作/郑州网站优化seo