news 2026/4/29 1:59:25

从迭代器到生成器

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
从迭代器到生成器

迭代器?

你有没有想过在python里for i in lit遍历一个列表,他究竟干了什么,为什么有的变量可以循环,而有的不可以for遍历?就比如说for i in 2,对一个数字遍历会报错TypeError: 'int' object is not iterable,这句话意思是int对象不是迭代器,看来想要迭代,还必须要有一定的属性,而这个属性就是__iter__以及__next__成员方法。

现在我用一个学生对象来举例迭代器,假设我想用for循环打印该学生的所有属性值:

  1. 第一步:对学生类创建__iter__成员方法
    该方法用于返回迭代器,你可以直接返回一个可迭代对象比如list或元组等内置对象,也可以返回self自己本身,只不过返回self本身,你就需要写__next__函数的逻辑。
  2. 第二步:添加__next__方法
    如果返回self本身作为迭代器就需要__next__方法,这个方法用于填写返回值的逻辑以及什么时候遍历终止。在迭代完毕时,需要抛出StopIteration来告知没有元素可以迭代!
classStudent:def__init__(self,name,age,stu_id,grade):# 初始化学生属性self.name=name# 姓名self.age=age# 年龄self.stu_id=stu_id# 学号self.grade=grade# 成绩def__iter__(self):# 迭代器初始化方法:返回迭代器对象本身# 定义一个索引,用来遍历属性列表self.index=0# 把对象的所有属性存入列表(固定遍历顺序)self.attributes=[self.name,self.age,self.stu_id,self.grade]returnselfdef__next__(self):# 迭代器核心:每次调用返回下一个属性ifself.index<len(self.attributes):# 获取当前属性value=self.attributes[self.index]# 索引+1,为下一次迭代做准备self.index+=1returnvalue# 迭代完毕,抛出停止迭代异常raiseStopIteration# 测试代码if__name__=='__main__':# 创建学生对象stu=Student("张三",18,"2025001",95)# 迭代遍历学生所有属性(for循环自动调用迭代器)print("学生所有属性:")forattrinstu:print(attr)# 手动调用迭代器(验证手写迭代器生效)print("\n手动迭代属性:")iter_obj=iter(stu)print(next(iter_obj))print(next(iter_obj))print(next(iter_obj))print(next(iter_obj))

所以定义迭代器有什么用,只是遍历?

迭代器在读取文件时大有用途,比如读取一个大型文件,你的目的是一行一行读取,在需要时读取下一行,于是你认为读取到列表里是不错的选择,但是发现一下子加载到内存就会有很大开销,于是迭代器登场了:

classLineReader:def__init__(self,file_path):# 打开文件self.file=open(file_path,'r',encoding='utf-8')# 标记是否已经读取完毕self.is_finished=Falsedef__iter__(self):# 迭代器返回自身returnselfdef__next__(self):# 如果已经读完,直接抛出停止迭代ifself.is_finished:self.file.close()# 关闭文件raiseStopIteration# 读取一行line=self.file.readline()# 如果读到空字符串,说明文件结束ifnotline:self.is_finished=Trueself.file.close()raiseStopIteration# 去掉换行符并返回returnline.strip()# ===================== 测试 =====================if__name__=='__main__':# 先创建一个测试文件 test.txtwithopen('test.txt','w',encoding='utf-8')asf:f.write("第一行:我是学生\n")f.write("第二行:学习Python\n")f.write("第三行:手写迭代器\n")f.write("第四行:逐行读取文件\n")# 使用我们的逐行读取迭代器print("=== 逐行读取内容 ===")reader=LineReader("test.txt")# for 循环自动迭代forlineinreader:print(line)

这个迭代器可以实现一行一行读取文件,而且内存开销也不大,读完时也会自动关闭文件。

生成器函数

如果上面读取文件的代码太复杂,生成器也是不错选择。
生成器函数里必须有yield,每次遍历生成器,yield都会返回一个生成的内容,并且函数阻塞到这里,等到下次调用该生成器,会从这里继续执行后面的代码。
生成器生成1-9的例子

deftest():a=1whilea<10:yielda a+=1foriintest():print(i)

他的逻辑是这样的:for循环先从生成器拿到第一个值1,此时生成器阻塞在a+=1处,当for循环打印1后,再次从生成器取值,生成器从阻塞的地方继续执行,a+=1后yield返回2以此类推.注意下面是错误的写法:

deftest():a=1ifa<10:yielda a+=1foriintest():print(i)

生成器遍历文件

defread_file(file_path):f=open(file_path,'r',encoding='utf-8')whileTrue:line=f.readline()ifnotline:breakyieldline f.close()# 遍历forlineinread_file("test.txt"):print(line)
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/29 1:57:04

地图层级·学习笔记

“最后,我会告诉你关于 Map 的事。” “Map,如你所知,存储了一组键值对。键必须是唯一的,但值可以是任何东西。如果你在一个Map中添加一个键值对,并且集合已经包含键,那么旧值将被新值替换。换句话说,键就像一个特殊的索引,可以是任何对象。” 映射是一个数学术语,表…

作者头像 李华
网站建设 2026/4/29 1:56:29

Steam Deck终极插件指南:5分钟解锁Decky Loader的全部潜力

Steam Deck终极插件指南&#xff1a;5分钟解锁Decky Loader的全部潜力 【免费下载链接】decky-loader A plugin loader for the Steam Deck. 项目地址: https://gitcode.com/gh_mirrors/de/decky-loader 想要彻底改变你的Steam Deck游戏体验吗&#xff1f;Decky Loader作…

作者头像 李华
网站建设 2026/4/29 1:56:25

Claude-mem在WindowsOpenclaw上的安装与调试指南

Windows 10 DeepSeek API OpenClaw 2026.4.24 claude-mem v12.4.7 2026-04-28 一、这篇教程解决什么问题 一句话定位&#xff1a;在 Windows 上把 claude-mem 持久化记忆插件接入 OpenClaw Gateway&#xff0c;使用 DeepSeek 作为 AI Provider&#xff0c;并解决 Windows …

作者头像 李华
网站建设 2026/4/29 1:56:15

剧院设备维保

剧院设备维保的关键要点剧院设备的稳定运行直接影响演出效果与安全。维保工作需结合专业性与系统性&#xff0c;以下从灯光、音响、机械三方面展开说明。灯光系统维护 定期检查灯具散热性能&#xff0c;避免因高温导致光衰或损坏。清洁透镜与反光碗时使用专用清洁剂&#xff0c…

作者头像 李华
网站建设 2026/4/29 1:53:17

OpCore-Simplify:三步搞定黑苹果配置的终极开源自动化工具指南

OpCore-Simplify&#xff1a;三步搞定黑苹果配置的终极开源自动化工具指南 【免费下载链接】OpCore-Simplify A tool designed to simplify the creation of OpenCore EFI 项目地址: https://gitcode.com/GitHub_Trending/op/OpCore-Simplify 还在为黑苹果配置的复杂性而…

作者头像 李华