Python迭代与生成器
1、迭代
_iter_ | 对象方法 | 可迭代对象,返回迭代器 |
---|---|---|
__next_ | 对象方法 | 迭代器对象,返回迭代中每一步的运算 |
iter(object) | 内置函数 | 得到object的迭代器 |
next(object) | 内置函数 | 得到迭代器的下一步迭代结果 |
1.1可迭代对象(Iterable)
如果一个对象实现了__iter__方法,那么这个对象就是可迭代对象。
from collections.abc import Iterable, Iterator class Color(object): def __init__(self): self.colors = ['red', 'white', 'black', 'green'] # 仅仅是实现了__iter__ 方法,在方法内部什么都不做 def __iter__(self): pass color_object = Color() # 判断是否为可迭代对象 print(isinstance(color_object, Iterable)) # True # 判断是否为迭代器 print(isinstance(color_object, Iterator)) # False
可迭代对象未必是迭代器,只是实现了_iter_方法,但是可迭代对象可以被for遍历,那是因为
for的工作原理: 1、使用iter获得可迭代对象的迭代器 2、反复对迭代器使用next方法 3、捕获StopIteration异常,退出循环
即for会使用iter去获得该可迭代对象的迭代器执行next方法遍历。
1.2迭代器
如果一个对象同时实现了__iter__方法和__next__方法,它就是迭代器。
迭代器一定是可迭代对象,因为迭代器要求必须同时实现__iter__方法和__next__方法, 而一旦实现了__iter__方法就必然是一个可迭代对象。但是反过来则不成立,可迭代对象可以不是迭代器。
from collections.abc import Iterable, Iterator class Color(object): def __init__(self): self.colors = ['red', 'white', 'black', 'green'] # 仅仅是实现了__iter__ 方法,在方法内部什么都不做 def __iter__(self): pass def __next__(self): pass color_object = Color() # 判断是否为可迭代对象 print(isinstance(color_object, Iterable)) # True # 判断是否为迭代器 print(isinstance(color_object, Iterator)) # True
1.3迭代器工作原理
内置函数iter获得迭代器
iter函数的作用是从可迭代对象那里获得一个迭代器
from collections.abc import Iterator lst_iter = iter([1, 2, 3]) print(isinstance(lst_iter, Iterator)) # Truefrom collections.abc import Iterator lst_iter = iter([1, 2, 3]) print(isinstance(lst_iter, Iterator)) # True
使用内置函数next遍历迭代器
内置函数next的功能是从迭代器那里返回下一个值
from collections.abc import Iterator lst_iter = iter([1, 2, 3]) print(next(lst_iter)) # 1 print(next(lst_iter)) # 2 print(next(lst_iter)) # 3 print(next(lst_iter)) # StopIteration
前3次调用next函数都能正常工作,第4次会抛出StopIteration异常,迭代器里已经没有下一个值了。
现在,让我们来做一个总结,遍历迭代器需要使用next方法,每调用一次next方法,就会返回一个值,没有值可以返回时,就会引发StopIteration异常。
为什么迭代器不能重复使用
iter函数每次会获得一个新的迭代器。
from collections.abc import Iterator lst_iter = iter([1, 2, 3]) print(next(lst_iter)) # 1 print(next(lst_iter)) # 2 到了这一步,你想从头开始遍历,那么重新获得一个迭代器使用 lst_iter_2 = iter([1, 2, 3]) print(next(lst_iter_2)) # 1 print(next(lst_iter_2)) # 2 print(next(lst_iter_2)) # 3
1.4 自定义可迭代对象和迭代器
实现__iter__方法和___next___方法
如果可迭代对象实现了iter__方法,那么内置函数iter会调用对象的__iter__方法方法返回一个迭代器,由于Color类实现了__next__方法,因此Color的实例也是迭代器,在__iter__方法里返回self即可。
我们使用内置函数next对迭代器进行遍历,在这个过程中,是在调用迭代器的__next__方法, 内置函数的作用是返回迭代器的下一个值,这个功能的实现,我们需要放在__next__方法中。
class Color(object): def __init__(self): self.index = -1 self.colors = ['red', 'white', 'black', 'green'] def __iter__(self): self.index = -1 return self def __next__(self): self.index += 1 if self.index >= len(self.colors): raise StopIteration return self.colors[self.index] color_object = Color() for color in color_object: print(color)
2、生成器
⽣成器也是⼀种迭代器,但是你只能对其迭代⼀次。这是因为他们并没有把所有的值存在 内存中,⽽是在运⾏时⽣成值。
在待遍历列表占用空间非常大时候,或者用到的遍历项目并不多时候,使用迭代的方式需要将整个迭代变量放入内存中,就会非常占用资源和不合适。生成器据前面的元素推断后面的元素,一边循环一边计算的机制叫generator。generator保存的是算法,每次调用next()
,就计算出下一个元素的值,直到计算到最后一个元素,没有更多的元素时,抛出StopIteration
的错误。
def intNum(): print("开始执行") for i in range(5): yield i print("继续执行") num = intNum()
和return 相比,yield 除了可以返回相应的值,还有一个更重要的功能,即每当程序执行完该语句时,程序就会暂停执行。不仅如此,即便调用生成器函数,Python 解释器也不会执行函数中的代码,它只会返回一个生成器(对象)。
要想使生成器函数得以执行,或者想使执行完 yield 语句立即暂停的程序得以继续执行,有以下 2 种方式:
- 通过生成器(上面程序中的 num)调用 next() 内置函数或者 next() 方法;
- 通过 for 循环遍历生成器。
#调用 next() 内置函数 print(next(num)) #调用 __next__() 方法 print(num.__next__()) #通过for循环遍历生成器 for i in num: print(i)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构