生成器(generator)和迭代(iterable , iterator, iteration)

在搞清楚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 异常,终止迭代。

原文地址:https://www.cnblogs.com/bradleon/p/5939461.html