在搞清楚Generator之前,我们先讨论一下 iterable , iterator, iteration
1.Iterable
我们知道,在Python中所有东西都是object, 比如说变量,容器,类对象都是object.
Iterable就是一种object,它具有__iter__ 或者__getitem__方法,能够返回一个iterator。
即iterable是给我们提供iterator的object.
2.Iterator
iterator 是一种用于 next 方法的object. 调用next()方法,可以每次取得iterator中的一个元素。
3.Iteration
在一个数据容器中遍历它的成员的过程 就是iteration。
4. Generator
Generator是那种通过yield方法来遍历元素的函数(即函数体中有yield存在的函数)。
Generator也是iterator,但是只能遍历它一次。它的好处是不存储元素值,也就不占内存空间。
关于Generator 可以看这个介绍:
http://www.ibm.com/developerworks/cn/opensource/os-cn-python-yield/index.html
用一个斐波那契数列的例子:
写法1: 直接打印出
def fab(max): n, a, b = 0, 0, 1 while n < max: print b a, b = b, a + b n = n + 1
这种方法能够将每一步的值打印出来,但是缺点是无法复用,比如算完fab(5)之后,再算fab(10)又要重新计算。
因此我们可能考虑将中间结果用一个list容器保留下来。
写法2: 用list保存结果。
def fab(max): n, a, b = 0, 0, 1 L = [] while n < max: L.append(b) a, b = b, a + b n = n + 1 return L
这种写法的缺陷是随着参数的增大,list中存储的数据会特别占内存。
因此我们引入generator,前文已经说了,它只能遍历一次,且不占内存。
写法3:使用generator
def fab(max): n, a, b = 0, 0, 1 while n < max: yield b # print b a, b = b, a + b n = n + 1
>>> for n in fab(5): ... print n
注意,此时的fab(5) 其实是一个iterator而不是一个函数了,我们只需要遍历它并且输出就可以了。generator在运行时,每次迭代都会保存这一次的yield的值,下次迭代就从这个值开始计算,因此不占内存。
注意: 在generator function中一般是没有return的,如果在执行中return,则抛出StopIteration 终止迭代。
在for循环一个generator时,是不会越界的。但是如果用iterator.next()这种方法遍历,则会产生越界情况,此时会抛出StopIteration 异常,终止迭代。