迭代器和生成器

迭代器和生成器

迭代器

什么是迭代呢?在编程中,迭代指的是通过重复执行某个操作,不断获取被迭代对象中的数据。这样的每一次操作就是就是一次迭代。

迭代器是具有迭代功能的对象。我们使用迭代器来进行迭代操作。

迭代器 = iter(容器)

>>> numbers=[1,2,3,4,5]
>>> it = iter(numbers)
>>> it
<listiterator object at 0x1007e6950>
>>>

for 循环的迭代过程

for 循环的迭代就是通过使用迭代器来完成的。它在背后所做的事情是:

  1. 对一个容器调用 iter() 函数,获取到该容器的迭代器
  2. 每次循环时对迭代器调用 next() 函数,以获取一个值
  3. 若捕获到 StopIteration 异常则结束循环

可迭代(Iterable)对象

并不是所有的对象都可以被 iter() 函数使用。

什么是可迭代(的)?
1、从表面来看,所有可用于 for 循环的对象是可迭代的,如列表、元组、字符串、集合、字典等容器
2、从深层来看,定义了 iter() 方法的类对象就是可迭代的。当这个类对象被 iter() 函数使用时,将返回一个迭代器对象。如果对象具有__iter__() 方法,则可以说它支持迭代协议。

判断一个已有的对象是否是可迭代的

1、 ‘iter’ in dir(list)
2、 isinstance(对象, Iterable)

自定义迭代器

class MyIterator:
    def __next__(self):
        代码块
    def __iter__(self):
        return self

生成器

刚才我们自定义了迭代器,其实创建迭代器还有另一种方式,就是使用生成器。

生成器是一个函数,这个函数的特殊之处在于它的 return 语句被 yield 语句替代。

def power_of_two():
	for exponent in range(11):	# range(11) 表示左闭右开区间 [0, 11),不包含 11
		yield 2 ** exponent		# 以 2 为底数求指数幂

生成器使用方法:
p = power_of_two()				# 以函数调用的方式创建生成器对象
next(p)							# 同样使用 next() 来取值

生成器的关键在于 yield 语句。yield 语句的作用和 return 语句有几分相似,都可以将结果返回。不同在于,生成器函数执行至 yield 语句,返回结果的同时记录下函数内的状态,下次执行这个生成器函数,将从上次退出的位置(yield 的下一句代码)继续执行。当生成器函数中的所有代码被执行完毕时,自动抛出 StopIteration 异常。

我们可以看到,生成器的用法和迭代器相似,都使用 next() 来进行迭代。这是因为生成器其实就是创建迭代器的便捷方法,生产器会在背后自动定义 iter() 和 next() 方法。

生成器表达式(Generator Expression)

可以用一种非常简便的方式来创建生成器,就是通过生成器表达式。生成器的写法非常简单,但是灵活性也有限,所能表达的内容相对简单。

生成器表达式的写法如下:
生成器 = (针对项的操作 for 项 in 可迭代对象)

>>> letters = (item for item in 'abc')
>>> letters
<generator object <genexpr> at 0x1007d4960>
>>> next(letters)
'a'
>>> next(letters)
'b'
>>>

列表生成式

[对项的操作 for 项 in 可迭代对象]