Python 迭代器与生成器
参考资料:
几分钟听懂迭代器 【哔哩哔哩教程】 (迭代器讲的很好)
Python迭代器与生成器介绍及在Pytorch源码中应用
Python 迭代器深入讲解 |【AsyncIO从入门到放弃#1】 (生成器讲得很好)
Python进阶 | 五分钟带你弄懂迭代器与生成器
迭代器
在python中,如果一个对象有__iter__和__next__方法,那么这个对象就是一个迭代器。
我们也可以调用__iter__函数把可迭代对象变为迭代器。
可迭代对象只有__iter__方法,没有__next__方法。
迭代器既有__iter__方法,也有__next__方法。(这也是迭代器协议所规定的)
在python中,这种前后都有双下划线的方法,既可以用 对象.__iter__() 来调用,也可以直接 iter(对象) 来调用。
对于一个for循环中的迭代,中间过程发生了两件事:
- __iter__函数把可迭代对象变为迭代器;
- 调用迭代器的__next__函数,返回一个元素。
我们自己创建一个简单的迭代器:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | class Iterator_test(): def __init__( self , data): self .data = data self .length = len (data) self .index = 0 def __iter__( self ): return self def __next__( self ): if self .index < self .length: self .index + = 1 return self .data[ self .index - 1 ] else : raise StopIteration case = Iterator_test([ 1 , 2 , 3 ]) # ========= 用循环的方式获取每一次迭代返回的值 =========== # for num in case: # print(num) # 输出:1 2 3 # ========= 调用iter方法获取每一次迭代返回的值 =========== print ( next (case)) # 输出:1 print ( next (case)) # 输出:2 print (case.__next__()) # 输出:3 print ( next (case)) # 输出:报错,StopIteration的错误 |
生成器
通常,我们把含有yield的函数称之为生成器函数generator function,把调用生成器函数返回的结果称为生成器generator (或者称为生成器对象)。
生成器是迭代器,不同的是生成器的实现更简洁。
__next__函数是由yield控制的。
return的作用是触发StopIteration异常。
生成器示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | def count(start = 0 , step = 1 , end = 8 ): n = start while n < end: yield n n + = step if __name__ = = '__main__' : c = count(end = 5 ) # c是生成器 # # ===== 用next函数来返回值 # print(next(c)) # 输出 0 # print(next(c)) # 输出 1 # ===== 用for循环来返回值,for循环实际上也是会调用next函数 for i in c: print (i, end = ' ' ) # 输出:0 1 2 3 4 |
总结一下yield的作用:
- 把函数变为生成器函数;
- 当程序运行到yield语句这里时,yield语句右边的对象作为next()的返回值;
- 返回一个值之后,程序会在yield语句这里暂停,当再次使用next()函数时,程序从该位置继续运行。
class实现的迭代器和yield实现的迭代器比较:
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 单元测试从入门到精通