接触Python迭代器之前,先来了解序列可以迭代的原因:iter函数
内置的iter
函数有以下作用。
- 检查对象是否实现了
__iter__
方法,如果实现了就调用它,获取一个迭代器。 - 如果没有实现
__iter__
方法,但是实现了__getitem__
方法,Python会创建一个迭代器,尝试按顺序(从0开始)获取元素。 - 如果尝试失败,抛出
TypeError: Object is not iterable
。
任何Python序列都是可迭代的原因是,他们都实现了__getitem__
方法,其实标准序列也都实现了__iter__
方法。ducking type认为只有都实现了__iter__
和__getitem__
方法,对象才叫可迭代对象。而goose type认为如果实现了__iter__
方法,对象就是可迭代的。
可迭代对象与迭代器的对比
一、可迭代对象
使用
__iter__
方法可以获取迭代器的对象。如果对象实现了返回迭代器的__iter__
方法,那么对象就是可迭代的。序列都可以迭代;实现了__getitem__
方法,而且其索引从0开始,也称对象可迭代。
总之,标准迭代器有两个方法
-
__next__
: 返回下一个可用元素,如果没有抛出StopIteration
异常。 -
__iter__
: 返回self。
二、迭代器
实现了无参的
__next__
方法,返回序列的下一个元素;如果没有元素,则抛出StopIteration
。
由于迭代器只需__iter__
和__next__
两个方法,所以除了调用__next__
方法,以及捕获StopIteration
异常外,没有办法检查是否还有遗留的元素。此外也没有办法复原迭代器。
注意:可迭代对象一定不能是自身的迭代器,也就是说,可迭代对象必须实现__iter__
方法,但不能实现__next__
方法
迭代器可以:
- 访问一个聚合对象的内容而无需暴露其内部表示
- 支持对聚合对象的多种遍历
- 为遍历不同聚合结构提供一个统一的接口(多态迭代)
三、生成器
只要Python函数体里有yield
关键字,该函数就是生成器函数,函数的返回值就是一个生成器对象。即生成器函数可以看做生成器工厂。
生成器函数会创建一个生成器对象,包装生成器函数的定义体。把生成器传给next()
函数时,生成器函数会向前,执行函数定义体中的下一个yield
语句,返回产出的值,并在函数定义体的当前位置暂停。最终函数的定义体返回时,外层的生成器对象会抛出StopIteration
异常。
通常在生成器函数中不予许出现return
语句,但是为了支持协程,Python进行了优化。