迭代器模式的定义
Provide a way to access the elements of an aggregate object
sequentially without exposing its underlying representation.
提供一种方法顺序地访问一组组合对象(一个容器)中的各个元素,而又不需要暴露该对象的内部细节。
## 迭代器模式的设计思想
迭代器模式也称为迭代模式。迭代器其实就是一个指向容器中当前元素的指针,这个指针可以返回当前所指向的元素,可以移到下一个元素的位置,通过这个指针可以遍历容器中的所有元素。迭代器一般至少有以下两种方法
current()
: 获取当前所指向的元素
next()
: 将指针移至下一个元素
这是最基本的两个方法,有了这两个方法,就可以从前往后地遍历各个元素。我们可以增加一些方法,比如实现从后往前遍历。一些更为丰富的迭代器功能如下
toBegin()
: 将指针移至起始的位置
toEnd()
: 将指针移至结尾的位置
current()
: 获取当前所指向的元素
next()
: 将指针移至下一个元素
previous()
: 将指针移至上一个元素
迭代器模式的抽象模型
代码框架
输出结果
Python 中的迭代器
Iterable
可以直接作用于 for
循环的对象统称为可迭代对象(Iterable),它们有如下两种类型
- 集合数据类型,如 list、tuple、dict、set、str 等
- 生成器(Generator),包括 () 语法定义的生成器和带 yield 的 generator
函数
Iterable 对象的代码示例如下
输出结果
关于生成器,在《流畅的 Python》中有这样的描述
Python 2.2(2001年)加入了 yield
关建字。这个关建字用于构建生成器(generator),其作用与迭代器一样。
所有生成器都是迭代器,因为生成器完全实现了迭代器接口。不过,根据《设计模式:可复用面向对象软件的基础》一书的定义,迭代器用于从集合中取出元素;而生成器用于“凭空”生成元素。通过斐波纳契数列能很好地说明二者之间的区别:斐波纳契数列中的数有无穷个,在一个集合中放不下。不过要知道,在
Python
社区中,大多数时候都把迭代器和生成器视作同一概念。
Iterator
生成器(Generator)不但可以作用于 for 循环,还可以被 next()
函数不断调用并返回下一个值,直到最后抛出 StopIteration
错误,表示无法继续返回下一个值。
可以被 next()
函数调用并不断返回下一个值的对象称为迭代器(Iterator)。
我们可以使用 isinstance()
来判断一个对象是否为 Iterable
对象或 Iterator 对象,示例代码如下
输出结果
Iterator 和 Iterable 的区别
Iterator 对象可以被 next() 函数不断调用并返回下一个值,直到最后抛出
StopIteration 错误,表示无法继续返回下一个值。
Iterable 对象不能被 next() 函数调用,可以用 iter()
函数将 Iterable 对象转成 Iterator 对象,示例代码如下
输出结果
使自定义的类具有
Iterable 或 Iterator 属性
要使自定义的类具有 Iterable 属性,需要实现 __iter__
方法。
要使自定义的类具有 Iterator 属性,需要实现 __iter__
和
__next__
方法,示例代码如下
输出结果
迭代器的类图
一个迭代器一般对应着一个容器类,而一个容器会包含多个元素,这些元素可能会有不同的子类。
在实际的项目开发中有可能会遇到一些更复杂的逻辑。例如,具有层级关系的组织架构:一个公司有
A、B、C
三个部门,每个部门有自己的成员,这时要遍历一个公司的所有成员,就有如下的类图关系
参考:
1、《人人都懂设计模式》(罗伟富) 2、《流畅的 Python》