从迭代器到生成器
迭代器你有没有想过在python里for i in lit遍历一个列表他究竟干了什么为什么有的变量可以循环而有的不可以for遍历?就比如说for i in 2,对一个数字遍历会报错TypeError: int object is not iterable,这句话意思是int对象不是迭代器看来想要迭代还必须要有一定的属性而这个属性就是__iter__以及__next__成员方法。现在我用一个学生对象来举例迭代器假设我想用for循环打印该学生的所有属性值第一步对学生类创建__iter__成员方法该方法用于返回迭代器你可以直接返回一个可迭代对象比如list或元组等内置对象也可以返回self自己本身只不过返回self本身你就需要写__next__函数的逻辑。第二步添加__next__方法如果返回self本身作为迭代器就需要__next__方法,这个方法用于填写返回值的逻辑以及什么时候遍历终止。在迭代完毕时需要抛出StopIteration来告知没有元素可以迭代classStudent:def__init__(self,name,age,stu_id,grade):# 初始化学生属性self.namename# 姓名self.ageage# 年龄self.stu_idstu_id# 学号self.gradegrade# 成绩def__iter__(self):# 迭代器初始化方法返回迭代器对象本身# 定义一个索引用来遍历属性列表self.index0# 把对象的所有属性存入列表固定遍历顺序self.attributes[self.name,self.age,self.stu_id,self.grade]returnselfdef__next__(self):# 迭代器核心每次调用返回下一个属性ifself.indexlen(self.attributes):# 获取当前属性valueself.attributes[self.index]# 索引1为下一次迭代做准备self.index1returnvalue# 迭代完毕抛出停止迭代异常raiseStopIteration# 测试代码if__name____main__:# 创建学生对象stuStudent(张三,18,2025001,95)# 迭代遍历学生所有属性for循环自动调用迭代器print(学生所有属性)forattrinstu:print(attr)# 手动调用迭代器验证手写迭代器生效print(\n手动迭代属性)iter_objiter(stu)print(next(iter_obj))print(next(iter_obj))print(next(iter_obj))print(next(iter_obj))所以定义迭代器有什么用只是遍历迭代器在读取文件时大有用途比如读取一个大型文件你的目的是一行一行读取在需要时读取下一行于是你认为读取到列表里是不错的选择但是发现一下子加载到内存就会有很大开销于是迭代器登场了classLineReader:def__init__(self,file_path):# 打开文件self.fileopen(file_path,r,encodingutf-8)# 标记是否已经读取完毕self.is_finishedFalsedef__iter__(self):# 迭代器返回自身returnselfdef__next__(self):# 如果已经读完直接抛出停止迭代ifself.is_finished:self.file.close()# 关闭文件raiseStopIteration# 读取一行lineself.file.readline()# 如果读到空字符串说明文件结束ifnotline:self.is_finishedTrueself.file.close()raiseStopIteration# 去掉换行符并返回returnline.strip()# 测试 if__name____main__:# 先创建一个测试文件 test.txtwithopen(test.txt,w,encodingutf-8)asf:f.write(第一行我是学生\n)f.write(第二行学习Python\n)f.write(第三行手写迭代器\n)f.write(第四行逐行读取文件\n)# 使用我们的逐行读取迭代器print( 逐行读取内容 )readerLineReader(test.txt)# for 循环自动迭代forlineinreader:print(line)这个迭代器可以实现一行一行读取文件而且内存开销也不大读完时也会自动关闭文件。生成器函数如果上面读取文件的代码太复杂生成器也是不错选择。生成器函数里必须有yield每次遍历生成器yield都会返回一个生成的内容并且函数阻塞到这里等到下次调用该生成器会从这里继续执行后面的代码。生成器生成1-9的例子deftest():a1whilea10:yielda a1foriintest():print(i)他的逻辑是这样的for循环先从生成器拿到第一个值1此时生成器阻塞在a1处当for循环打印1后再次从生成器取值生成器从阻塞的地方继续执行a1后yield返回2以此类推.注意下面是错误的写法deftest():a1ifa10:yielda a1foriintest():print(i)生成器遍历文件defread_file(file_path):fopen(file_path,r,encodingutf-8)whileTrue:linef.readline()ifnotline:breakyieldline f.close()# 遍历forlineinread_file(test.txt):print(line)
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2564189.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!