[Python学习]Iterator 和 Generator的学习心得

Iterator是迭代器的意思,它的做用是一次产生一个数据项,直到没有为止。这样在 for 循环中就能够对它进行循环处理了。那么它与通常的序列类型(list, tuple等)有什么区别呢?它一次只返回一个数据项,占用更少的内存。但它须要记住当前的状态,以便返回下一数据项。它是一个有着next()方法的对象。而序列类型则保存了全部的数据项,它们的访问是经过索引进行的。node

使用Iterator的好处除了节省内存外,还有一个好处就是能够把非线性化的处理转换成线性化的方式来进行处理。如对一棵树的访问,传统的方法可使用递归函数来处理,下面是对树的一个中序遍历的示例:python

例1:

def deal_tree(node):
    if not node:
        return
    if node.leftnode:
        deal_tree(node.leftnode)
    process(node)
    if node.rightnode:
        deal_tree(node.rightnode)

deal_tree(root)函数

能够看出,对结点的处理函数与递归函数是混在一块儿的,不是很清晰。使用Iterator的方式改写后为:学习

例2:

1    def walk_tree(node):
2        if not node:
3            return
4        if node.leftnode:
5            for i in walk_tree(node.leftnode):
6                yield i
7        yield node
8        if node.rightnode:
9            for i in walk_tree(node.rightnode):
10               yield i
11
12   for node in wald_tree(root):
13       process(node)orm

生成结点的过程仍然是一个递归过程,但对于返回后的结点的处理就变成了线性化的处理,结构上要清晰多了。第5-6,9-10行要特别注意,若是不这样处理直接调用walk_tree的话,其实返回的是一个Iterator对象,而不是想要的元素。对象

象上面的walk_tree函数在 Python 中能够叫做Generator–产生器,它的做用是生成一个Iterator的对象。那么它主要是将一个函数过程进行封装,转化为Iterator对象,每执行到yield语句时,函数的状态,数据都保存起来,而后返回相应的值。取下一个值的时候,再从上次运行的地方继续运行,若是赶上yield语句,则再次保存状态,返回结果,若是不存在值了,则自动引起一个异常StopIteration,从而Iterator再也不产生新的值。今后处咱们能够了解,这里的Iterator只能够遍历一次,但并不是全部的都是这样,你彻底能够对其进行控制。blog

下面我再介绍一下如何构造自已的Iterator。很简单,建立一个类,知足Iterator的协议,也就是要定义__iter__方法,它返回一个Iterator对象,这个对象必须有next方法,所以咱们能够总结出两种对象模式:递归

class A:
    def __iter__(self):
        return self

    def next(self):
        if has_next_value(self):
            return next_value
        else:
            raise StopIteration索引

class B:
    def __iter__(self):
        return iterator_obj内存

A,B分别为两种对象模式(都是示例代码)。模式A表示,在A中定义了next方法,所以__iter__简单地返回自身便可。当不存在下一个值时,引起StopIteration异常。模式B表示,它使用了其它的Iterator对象,所以只须要定义__iter__便可,next不须要定义,由于返回的Iterator对象已经含有next方法了。若是是自已实现next方法,那么在返回值以前须要记住当前的状态,以便下一次运行时,能够取下一个值。

第2个例子好象与这里讲的不同啊。这就是前面讲的Generator,它的做用就是把一个函数转换成一个Iterator,它自动保存状态,中间数据,引起异常,所有是自动化了。并且它只能够遍历一次。若是想再次遍历,只有从新生成新的Iterator对象才能够。

在最新的 Python 2.4 版中新增了Genetaor Expression方式,它是用来生成简单的,在函数调用须要序列参数时的一种Iterator写法,语法就象是list comprehension的格式,如:

>>> sum(i*i for i in range(10))                 # sum of squares
285

不过这种写法必需要在小括号对中,所以它的使用是有限的。它的目的主要是想更好的使用内存。

前面咱们提到不是全部的Iterator只能够遍历一次(使用Generator生成的只能遍历一次),你彻底能够控制它从新遍历。好比咱们能够在Iterator对象中增长一个复位方法,用来将内部的计数恢复到开始状态,这样咱们就能够从新遍历了。

下面咱们总结一下:

Iterator对象:具备__iter__方法,和next方法。当没有新值时引起StopIteration异常。

Iterator的好处:在某些状况下可使程序结构清晰,如将递归等非线性处理转为线性处理。能够减小内存的占用。

Generator:将一个函数转化成Iterator对象的方法。使用它只须要在函数中须要返回值的时候调用yield语句。它是生成Iterator对象的简单方法,只适用于函数。

相关文章
相关标签/搜索