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 种方式:

  1. 通过生成器(上面程序中的 num)调用 next() 内置函数或者 next() 方法;
  2. 通过 for 循环遍历生成器。
#调用 next() 内置函数
print(next(num))
#调用 __next__() 方法
print(num.__next__())
#通过for循环遍历生成器
for i in num:
print(i)
posted @   饮一杯天上水  阅读(45)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
点击右上角即可分享
微信分享提示