先说结论:
① 所有的生成器都是迭代器.
② 迭代器(iterator)用类实现, 生成器(generator)用函数实现
Python 中任意的对象,只要它定义了可以返回一个迭代器的__iter__
方法,或者定义了可以支持下标索引的__getitem__
方法,那么它就是一个可迭代对象(如: tuple, list, dict)
1.迭代器
迭代器的实现是基于类, 要使得类的实例是一个生成器, 需要满足2个条件.
- 定义一个__iter__方法, 内容要 return self
- 定义一个__next__方法(Python 2中 是 next 方法)
一个代码实例:
In [1]: class Squares(object):
...: def __init__(self, start, stop):
...: self.start = start
...: self.stop = stop
...: def __iter__(self):
...: return self
...: def __next__(self): # next in Python 2
...: if self.start >= self.stop:
...: raise StopIteration
...: current = self.start * self.start
...: self.start += 1
...: return current
In [2]: iterator = Squares(1, 4)
In [3]: next(iterator)
Out[3]: 1
In [4]: iterator.__next__()
Out[4]: 4
In [5]: next(iterator)
Out[5]: 9
In [6]: next(iterator)
---------------------------------------------------------------------------
StopIteration
如上代码, 定义一个类Squares, 实现__iter__和__next__方法, 该类的一个实例iterator就是一个迭代器, 可以对其使用关键字next来依次获取迭代器中的内容(即调用__next__函数). next(iterator) == iterator.__next__()
可以使用关键字iter() 将一个Iterable对象转换成迭代器.
In [7]: iterator = iter([1,2,3,4,5])
In [8]: next(iterator)
Out[8]: 1
In [9]: next(iterator)
Out[9]: 2
2. 生成器
生成器可以认为是一个简化版的迭代器, 生成器的实现是基于函数. 再函数中使用关键字“yield” 而不是通常用的return. yield作为生成器执行的暂停恢复点, 每次调用next, 生成器函数执行到yield语句, 会挂起,并保存当前的上下文信息. 知道下一个next触发生成器继续执行.
使用生成器来实现之前的Squares迭代器
In [1]: def squares(start, stop):
...: for i in range(start, stop):
...: yield i * i
In [2]: generator = squares(1, 4)
In [3]: next(generator)
Out[3]: 1
In [4]: next(generator)
Out[4]: 4
In [5]: next(generator)
Out[5]: 9
In [6]: next(generator)
---------------------------------------------------------------------------
StopIteration
如上例代码可见, 函数squares返回的是一个生成器.
第一次调用next(generator) for 循环遍历到 i=1, 然后通过yield返回当前值 1, 函数被挂起.
第二次调用next(generator) for 循环继续执行, 遍历到 i=2 然后通过yield返回当前值 4, 函数再次挂起.
直到遍历结束, 抛出StopIteration 异常
可以在函数中使用 while True语句, 返回永远不会结束的生成器
3. 对比
迭代器 Iterator | 生成器 Generator |
---|---|
用类实现 | 用函数实现 |
迭代器使用 iter() 和 next() 函数 | 生成器使用 yield 关键字 |
每个生成器都是一个迭代器 | |