Python | 深入理解循环和迭代( 三 )


这就意味着,可以将迭代器对象作为iter函数的参数,生成一个新的迭代器对象 。不是吗?
>>> numbers = [1, 2, 3]>>> iterator1 = iter(numbers)>>> iterator2 = iter(iterator1) # 迭代器对象作为参数
以上最终得到的iterator2是一个迭代器 。不过,要注意,iterator1和iterator2的关系:
>>> iterator1 is iterator2True
iter函数的参数如果是一个迭代器,返回对象仍然是该迭代器对象自身 。
结论:迭代器是可迭代对象,所有迭代器都是自己的迭代器 。
def is_iterator(iterable):return iter(iterable) is iterable
困惑了吗?
继续 。
迭代器没有长度,因此无法索引 。这个认识必须要建立起来 。
>>> numbers = [1, 2, 3, 5, 7]>>> iterator = iter(numbers)>>> len(iterator)TypeError: object of type 'list_iterator' has no len()>>> iterator[0]TypeError: 'list_iterator' object is not subscriptable
从Python程序员的角度来看,使用迭代器可以做的唯一有用的事情就是:将迭代器传给内置的next函数、或遍历迭代器:
>>> next(iterator)1>>> list(iterator)[2, 3, 5, 7]
如果我们第二次遍历迭代器,我们将一无所获:
>>> list(iterator)
这就是说,迭代器可以认为是一次性的惰性的可迭代对象,这意味着它们只能遍历一次 。

Python | 深入理解循环和迭代

文章插图
 
正如上表中所示,可迭代对象并不总是迭代器,但迭代器总是可迭代对象:
所谓迭代器协议,即:
 
  1. 可以作为next函数的参数,从而获得对象的下一项,或者在没有其他项时引发StopIteration异常 。
  2. 可以作为iter函数的参数,并返回自身 。
 
反过来说,也成立:
 
  1. 任何可以传给iter而没有引发TypeError的对象都是可迭代对象 。
  2. 任何可以传给next而没有引发TypeError的对象都是迭代器 。
  3. 任何在传给iter时返回自身的对象都是迭代器 。
 
这是Python中的迭代器协议 。
迭代器无处不在
Python中的迭代器很多,例如:
>>> letters = ['a', 'b', 'c']>>> e = enumerate(letters)>>> e>>> next(e)(0, 'a')
在Python3中,zip、map和filter对象也是迭代器 。
>>> numbers = [1, 2, 3, 5, 7]>>> letters = ['a', 'b', 'c']>>> z = zip(numbers, letters)>>> z>>> next(z)(1, 'a')
Python中的文件对象也是迭代器 。
>>> next(open('hello.txt'))'hello worldn'
在Python、标准库和第三方Python库中还有许多内置的迭代器 。
至此,已经可以给出完美的解释了 。




推荐阅读