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

生成器与迭代器

在Python中,迭代器和生成器是处理数据流的灵魂,它们的核心目标只有一个————节省内存。

迭代器(Iterator)

直观解释:

  • 迭代器就是能够将一堆数据一个个吐出来的对象,而不是一次性输出。
  • 比如:
nums = [1, 2, 3]
it = iter(nums)  # 获取迭代器print(next(it))  # 1
print(next(it))  # 2
print(next(it))  # 3

本质定义:

  • 任何一个对象要想成为迭代器,需要满足以下两个方法:
__iter__()   # 返回自身
__next__()   # 返回容器的下一个元素。如果没有元素了,则抛出 StopIteration 异常。

自定义生成器

class MyIterator:def __init__(self, n):self.n = nself.cur = 0def __iter__(self):return selfdef __next__(self):if self.cur < self.n:self.cur += 1return self.curelse:raise StopIterationif __name__ == '__main__':it = MyIterator(3)for i in it:print(i)
  • 结果:
    image
特点:
  • 惰性计算(用一个取一个)
  • 节省内存
  • 只能往前走,不能回退

生成器(Generator)

直观理解:

  • 生成器是“自动帮你写好的迭代器”。不用写 next,Python帮你做。
  • 因此生成器也是一种特殊的迭代器。

定义方式:

  1. 使用yield关键字
def gen():yield 1yield 2yield 3if __name__ == '__main__':g = gen()print(g)print(next(g))print(next(g))print(next(g))
  • 结果:
    image
  • 执行过程:函数执行到 yield 关键字
    • 暂停
    • 返回当前值
    • 下次从暂停位置继续
  1. 生成器表达式(类似列表推导式)
g = (x*x for x in range(5))
  • 对比:
[x*x for x in range(5)]  # 列表(一次性全部生成)
(x*x for x in range(5))  # 生成器(按需生成)

两者对比

对比点 迭代器 生成器
定义方式 类实现 yield / 表达式
实现难度 非常简单
本质 手写迭代逻辑 自动生成迭代器
是否惰性
是否是迭代器 ✔(生成器本身就是迭代器)
  • 总结:生成器 = 更高级、更方便的迭代器

可迭代对象 (Iterable)

  • 可迭代对象 (Iterable): 像 list, dict, str 这种可以用 for 循环遍历的都是可迭代对象,但它们不是迭代器。
  • Python 规定:一个对象内部实现了 iter() 方法,就是可迭代对象。
  • 转换: 可以用 iter() 函数把可迭代对象转成迭代器。

三者之间的关系:

可迭代对象 Iterable↓ 调用 __iter__() 可以得到
迭代器 Iterator↓ 生成器是它的子类
生成器 Generator

yield和return的区别

特性 return yield
函数性质 普通函数 生成器函数 (Generator)
退出机制 彻底结束:函数执行完毕,销毁局部变量 暂停执行:挂起函数,保存当前所有状态
返回值次数 只能返回 1 次(或者返回一个包含多数据的元组) 可以返回多次(每次调用返回一个值)
状态保存 不保存状态,下次调用从头开始 自动保存:下次调用从上次停止的地方继续
内存占用 高(一次性返回所有数据) 低(按需生成,一次只占一个值的空间)

举例:

  • 当你调用一个带 return 的函数时,它会从第一行开始运行,直到遇到 return。一旦 return 执行,函数就把结果扔给调用者,然后原地解散,内存中的局部变量全部回收。
def normal_func():return "第一步"return "第二步"  # 永远不会被执行print(normal_func()) # 输出: 第一步
  • 当你调用带 yield 的函数时,它并不会立即执行代码,而是返回一个生成器对象。每次你对这个对象执行 next(),它就运行到下一个 yield 处,把值交给你,然后原地休眠。它会记住所有的变量、当前的循环进度和执行行数。
def generator_func():yield "第一步"yield "第二步"yield "第三步"gen = generator_func()
print(next(gen)) # 输出: 第一步 (函数在此处暂停)
print(next(gen)) # 输出: 第二步 (函数从刚才暂停的地方恢复)
  • 在 Python 3.3 之后,同一个函数里可以同时出现 return 和 yield:
    • yield 负责产生数据流。
    • return 负责彻底结束生成器。如果在生成器中执行了 return value,这实际上会引发一个 StopIteration 异常,并将 value 作为异常的说明信息。
http://www.jsqmd.com/news/689579/

相关文章:

  • 别再死记硬背了!用Python仿真带你搞懂发电机纵差、横差保护原理
  • 保姆级教程:在Ubuntu 20.04 ROS Noetic下,用奥比中光Astra Pro完成相机标定(附常见报错解决)
  • 国信QMT vs 国金MiniQMT:实测哪个能真正下载可用的历史Tick数据?
  • 用Python和OpenCV搞定车道线曲率计算:从图像处理到实际距离的保姆级教程
  • 别再傻傻分不清!VCC、VDD、VSS、VEE、VPP,5分钟帮你理清电路图上的电源符号
  • 2026年头皮抗衰行业靠谱GEO优化服务商选型与能力评估分析报告 - 商业小白条
  • 车载ECU开发效率飙升217%?VSCode 2026适配实测报告:12家OEM验证的4项必须启用的隐藏设置
  • MTK Filogic 630方案首秀:中兴E1630拆解看MT7916的升级点
  • 【2026年最新600套毕设项目分享】微信小程序的专利服务系统(30146)
  • 保姆级教程:用OpenCV和PCL库给激光雷达点云上色(附完整C++代码)
  • 2026年少儿编程行业专业AI搜索优化服务商选型分析与主流机构推荐 - 商业小白条
  • 从Flash到SAR:一张图看懂主流ADC结构怎么选(2024版)
  • 26-4-23日志 - Ghost
  • 保姆级教程:在Ubuntu上为AM5728开发板交叉编译GPSD 3.18(附libusb/ncurses依赖库完整配置)
  • 避开Latex!用Word向ACM会议投稿的完整攻略:从模板适配到TAPS最终提交
  • 智能合约开发框架对比
  • 别再只盯着运放了!用TI INA826这类仪表放大器搞定传感器信号调理,实测避坑指南
  • 从入门到精通:AI产品经理的完整学习指南与实战路径
  • 告别Grbl依赖:手把手教你用STM32CubeMX和emWin搭建带U盘脱机功能的CNC控制界面
  • 电荷泵在嵌入式系统中的应用:从LCD驱动到EEPROM编程
  • IGBT驱动信号里的‘空白时间’:手把手教你分析SVPWM/SPWM中的死区效应与谐波
  • Spring Boot Admin Server 2.3.1 保姆级搭建教程:从零到UI界面,含Spring Security安全配置避坑指南
  • ADS负载牵引实战:从CGH40010F管子的1.6GHz仿真到稳定电路设计,一步步教你优化PA性能
  • 【2026年最新600套毕设项目分享】微信小程序的酒店管理系统(30147)
  • 虾皮 大数据开发工程师面试题精选:10道高频考题+答案解析(附PDF)
  • 别再傻傻分不清了!一文讲透增量式与绝对式编码器到底怎么选(附选型避坑指南)
  • C#借助EPPlus高效处理海量Excel数据:从导入到写入的实战解析
  • FeNOMS架构:存储内计算加速质谱数据分析
  • 2026年最新|手把手教你用EasyClaw PPT大师:免费一键生成PPT,告别手动排版
  • Excel实战:用PCA给你的客户数据‘瘦身’,5步完成特征筛选与可视化