迭代器与生成器
我们知道,可以使用for循环操作的数据类型有list、str、dict、set、tuple,以及生成器,它们都是可迭代对象,可以被next()函数调用并不断返回下一个值的对象称为迭代器(Iterator)。
迭代器包含有next方法的实现,在正确的范围内返回期待的数据以及超出范围后能够抛出StopIteration的错误停止迭代。
list、dict、str虽然是可迭代对象,但并不是迭代器,python中的迭代器是一个数据流,或者有序序列,但是我们无法提前知道序列的长度,只能通过next函数不断计算下一个数据。我们可以通过iter函数将它们转变为迭代器,其实python中的for本质上是通过不断调用next函数实现的。
列表是python中非常重要的数据结构,但是,如果我们要创建一个很大的列表,其中包含很多个元素(例如10亿个),如果把每个元素放在列表中就会超出内存的限制,而且我们有时只访问前面几个元素,后面的内存就会浪费掉。如果我们根据前一个元素就可以获得下一个元素,即知道元素的获取规则,就不必创建完成的列表,在python中这种一边循环一边生成列表元素的机制称为生成器。
生成器函数是用def定义的,利用关键字yield一次性返回一个结果,阻塞后重新开始。生成器是一种特殊的迭代器。
下面,我们实现一个我们自己的range方法,以下函数实际上就是一个生成器,实现从0到n-1的数字生成,yield关键字可以理解为return,但是不同的是,执行完代码后,又会返回到函数yield处继续执行。
def my_range(n):
i = 0
while i < n:
yield i
i = i + 1
我们打印出来该函数的结果,可以发现是一个生成器:
print(my_range(5))
# <generator object my_range at 0x0000023D3C9270A0>
如何使用生成器?最简单的方式就是使用for循环,逐一取出生成器生成的元素,生成器每次只生成一个元素:
for i in my_range(5):
print(i)
# 0
# 1
# 2
# 3
# 4
此外,还可以使用next方法,每次只取一个元素:
a = my_range(5)
print(next(a))
# 0
print(next(a))
# 1
print(next(a))
# 2
有关迭代器和生成器的更多内容可以参考大佬博客。