迭代器、生成器、可迭代对象
迭代器出现的原因
Python中的列表,有可能会占用很大的空间。而迭代器,它是每一次用__next__调用时才计算出值,这会节省内存空间。迭代器、生成器、可迭代对象的关系
可迭代对象一般是列表、元组、字典、字符串等可以For循环的对象。可通过以下语句判断是不是可迭代对象。
1 2 3 4 | from collections.abc import Iterator, Iterable l = [ 1 , 2 , 3 , 4 , 5 ] print ( isinstance (l, Iterable)) # True |
而且每个可迭代对象都有__iter__方法,并且此方法返回一个迭代器。
那么什么是迭代器呢?它与可迭代对象有什么关系?为什么for循环可以得出每人元素的值?那是因为可迭代对象有一个记录员,可记录当前位置。而这个记录员就是迭代器,迭代器需要实现__iter__、__next__这两个方法。可迭代对象可生成迭代器,如下:
1 2 3 | l = [ 1 , 2 , 3 , 4 , 5 ] it = iter (l) print ( isinstance (it, Iterator)) # True |
每个迭代器都有__next__方法和__iter__方法。而生成器是迭代器的一种,除了有__next__方法以外,还要用到yield。yield一般会用到自定义的函数中,但调用此函数时不会执行,而是会生成生成器。要调用此函数,需要用到__next__方法。
for循环的本质
其实for循环一个可迭代对象,为我们做了以下事情
1、通过可迭代对象生成一个迭代器
2、调用迭代器的__next__方法,生成值
3、遇到错误时,就退出
以下程序就说明了这个问题
1 2 3 4 5 6 7 8 9 10 | l = [ 1 , 2 , 3 , 4 , 5 ] for i in l: print (i) # 以上for循环等同于以下效果 it = iter (l) while True : try : print (it.__next__()) except StopIteration: break |
自定义可迭代对象和迭代器
例子如下:
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 29 30 31 32 33 34 35 | class List ( object ): # 自定义可迭代对象,必须要有__iter__方法 def __init__( self ): self .item_list = [] def append( self , val): self .item_list.append(val) def __iter__( self ): # 自定义,必须要返回迭代器,此处返回自定义迭代器ListIterator return ListIterator( self .item_list) class ListIterator( object ): # 自定义迭代器,必须要定义__iter__和__next__方法 def __init__( self , item_list): self .index = 0 self .item_list = item_list def __iter__( self ): return self def __next__( self ): if self .index < len ( self .item_list): i = self .index self .index + = 1 return self .item_list[i] else : raise StopIteration my_list = List () my_list.append( '辉' ) my_list.append( '玲' ) my_list.append( '婧' ) my_list.append( '正' ) for i in my_list: print (i) |
生成器
例一、斐波那契数列1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | def fib(m): n, a, b = 0 , 0 , 1 while n < m: yield b # 每一次用__next__调用时会在此结束,下一次调用时执行yield下面的语句 a, b = b, a + b n + = 1 f = fib( 5 ) # 生成生成器,不会调用,要调用就用__next__方法 # while True: # try: # print(f.__next__()) # except StopIteration: # break for i in f: print (i) # 斐波那契数列结束 |
例二、经典的生产者、消费都模型
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | def consumer(name): print ( '%s要准备吃包子了' % name) while True : n = yield print ( '%s吃了%s个包子' % (name, n)) def producer(name): print ( '%s准备制造包子了' % name) c1 = consumer( 'Daughter' ) c2 = consumer( 'Son' ) c1.__next__() c2.__next__() print ( '-' * 40 ) while True : time.sleep( 3 ) print ( '%s已经制造了2个包子' % name) c1.send( 1 ) # 可发送给yield c2.send( 1 ) print ( '-' * 40 ) producer( 'Father' ) # 消费者、生产都模型结束 |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 上周热点回顾(3.3-3.9)
· AI 智能体引爆开源社区「GitHub 热点速览」