迭代,是重复反馈过程的活动,通常是为了逼近所需目标或结果。每对过程重复一次称为一次“迭代”,而每次迭代得到的结果会作为下一次迭代的初始值。在 Python 中,迭代是访问集合型数据的一种方式,对于字符串、列表、元组、集合和字典,都可以使用迭代来遍历其中的每个元素,而这些可以使用 for 循环遍历的对象也被称为可迭代对象。
迭代器是将一个可迭代对象添加了迭代遍历特性后变换而成的对象。迭代器有以下特点:
- 从集合的第一个元素开始访问,直到所有的元素被访问完结束;
- 可以记住遍历的位置;
- 只能向前不能后退。
可迭代对象不一定是迭代器,但迭代器一定是可迭代对象,二者的关系可以用图 1 表示。
图 1:可迭代对象与迭代器的关系
可以使用 isinstance( ) 函数检查一个对象是迭代器还是可迭代对象,例如:
from collections import Iterable, Iterator
isinstance('abc', Iterable)
isinstance([1,2,3], Iterable)
isinstance((1,2), Iterable)
isinstance({1, 2}, Iterable)
isinstance(123, Iterable)
isinstance('abc', Iterator)
isinstance([1,2,3], Iterator)
isinstance((1,2), Iterator)
isinstance({1,2}, Iterator)
isinstance(123, Iterator)
上述代码的运行结果如下所示:
>>> from collections import Iterable, Iterator
>>> isinstance('abc', Iterable)
True
>>> isinstance([1,2,3], Iterable)
True
>>> isinstance((1,2), Iterable)
True
>>> isinstance({1, 2}, Iterable)
True
>>> isinstance(123, Iterable)
False
>>> isinstance('abc', Iterator)
False
>>> isinstance([1,2,3], Iterator)
False
>>> isinstance((1,2), Iterator)
False
>>> isinstance({1,2}, Iterator)
False
>>> isinstance(123, Iterator)
False
可见,字符串、列表、元组、字典都是可迭代对象,普通数字不是可迭代对象;这些数据类型的对象都不直接是迭代器。
区分迭代器和可迭代对象的原则是:
- 具有 __iter__() 方法的对象称为可迭代对象。该方法可获取其迭代器对象;
- 具有 __iter__() 方法和 __next__() 方法的对象称为迭代器对象。该方法能够自动返回下一个结果,当到达序列结尾时,引发 StopIteration 异常。
迭代对象本身不一定是迭代器,但可以通过其 __iter__() 方法得到对应的迭代器对象。定义可迭代对象,必须实现 __iter__() 方法;定义迭代器,必须实现 __iter__() 和 __next__() 方法。
对于可迭代对象,可以使用 iter( ) 函数得到其对应的迭代器对象,使用 next( ) 函数获取该迭代器对象当前返回的元素,例如:
l = [1, 2, 3]
iterName=iter(l)
print(iterName)
print(next(iterName))
print(next(iterName))
print(next(iterName))
print(next(iterName))
上述代码的运行结果如下所示:
>>> l = [1, 2, 3]
>>> iterName=iter(l)
>>> print(iterName)
<list_iterator object at 0x0000017D355F8D00>
>>> print(next(iterName))
1
>>> print(next(iterName))
2
>>> print(next(iterName))
3
>>> print(next(iterName))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
print(next(iterName))
StopIteration
可见,iter( ) 函数与 __iter__() 方法联系非常紧密,iter()是直接调用该对象的 __iter__() 方法,并将其返回结果作为自己的返回值,next( ) 函数则是调用该对象的 __next__() 方法获取当前元素。上例中在得到列表l最后一个元素3后再一次使用了 next( ) 函数,而此时列表l中已经没有可获取的元素了,所以抛出了异常。
因此,通俗地说,可以将迭代器简单理解为“内置了 for 循环的可迭代对象”,每使用 next( ) 函数访问一次迭代器对象,其在返回当前元素的同时,内部指针将指向下一个元素。