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

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

例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)

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

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

下面我再介绍一下如何构造自已的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对象的简单方法,只适用于函数。

[Python学习]Iterator 和 Generator的学习心得的更多相关文章

  1. python类,魔术方法等学习&&部分ssti常见操作知识点复习加深

    python类学习&&部分ssti常见操作知识点复习加深 在做ssti的模块注入的时候经常觉得自己python基础的薄弱,来学习一下,其实还是要多练习多背. 在python中所有类默认 ...

  2. 孤荷凌寒自学python第六十五天学习mongoDB的基本操作并进行简单封装4

    孤荷凌寒自学python第六十五天学习mongoDB的基本操作并进行简单封装4 (完整学习过程屏幕记录视频地址在文末) 今天是学习mongoDB数据库的第十一天. 今天继续学习mongoDB的简单操作 ...

  3. 孤荷凌寒自学python第六十四天学习mongoDB的基本操作并进行简单封装3

    孤荷凌寒自学python第六十四天学习mongoDB的基本操作并进行简单封装3 (完整学习过程屏幕记录视频地址在文末) 今天是学习mongoDB数据库的第十天. 今天继续学习mongoDB的简单操作, ...

  4. Python之路,Day21 - 常用算法学习

    Python之路,Day21 - 常用算法学习   本节内容 算法定义 时间复杂度 空间复杂度 常用算法实例 1.算法定义 算法(Algorithm)是指解题方案的准确而完整的描述,是一系列解决问题的 ...

  5. Python学习笔记之--我又开始学习Python了(随时更新)

    2019.02.09 更新 Python 学习计划已经开始几天了,跟着一本叫<Django for beginner>的书籍在学习用Django搭建自己的第一个网站,目前已经进行到第三章, ...

  6. 转:python的nltk中文使用和学习资料汇总帮你入门提高

    python的nltk中文使用和学习资料汇总帮你入门提高 转:http://blog.csdn.net/huyoo/article/details/12188573 nltk的安装 nltk初步使用入 ...

  7. python的加密模块(md5,sha,crypt)学习

    python的加密模块(md5,sha,crypt)学习 命令行使用python MD5: yinguicai@Cpl-IBP-Product:~/data/work/svn/v1.4.0_dev/A ...

  8. Python——轻量级web服务器flask的学习

    前言: 根据工程需要,开始上手另一个python服务器---flask,flask是一个轻量级的python服务器,简单易用.将我的学习过程记录下来,有新的知识会及时补充. 记录只为更好的分享~ 正文 ...

  9. 学习《零基础入门学习Python》电子书PDF+笔记+课后题及答案

    初学python入门建议学习<零基础入门学习Python>.适合新手入门,很简单很易懂.前一半将语法,后一半讲了实际的应用. Python3入门必备,小甲鱼手把手教授Python,包含电子 ...

随机推荐

  1. AlloyTouch全屏滚动插件搞定顺滑H5页

    使用姿势 在设计全屏滚动插件的时候,希望开发者几乎: 不用写任何脚本快速生成精致H5 支持PC滚轮和移动触摸 酷炫的转场动效 灵活的时间轴管理 一切皆可配置 但是不写脚本肯定没有灵活性咯?!不是的.这 ...

  2. Fluent UDF【1】:简介

    前面基本完成了动网格专题的发布,不过还是有一些内容并没有更新进去,比如说in-cylinder.接触检测.2.5D网格重构等.不过这些都是小技巧,写起来挺麻烦,以后有时间再通过案例视频的方式讲解好了. ...

  3. JMeter测试工具中的参数化使用[函数助手]

    下面是我使用JMeter测试工具对某项目中的一个http接口进行测试时的配置参数,使用到了JMeter的随机函数: 在发送POST请求时,需要发送json格式的数据,其中使用到JMeter的" ...

  4. Is there a way to get a Cursor from a GreenDao Query object?

    转:http://stackoverflow.com/questions/13584876/is-there-a-way-to-get-a-cursor-from-a-greendao-query-o ...

  5. 服务端测试环境hosts配置检查脚本

    [本文出自天外归云的博客园] 问题 由于A测试环境和B测试环境相互耦合,B测试环境切换导致我方测试环境需要更改后台服务器的响应配置.若多台服务器中有一台服务器没有更改配置,则在测试过程中将会出现问题. ...

  6. poj1077(康托展开+bfs+记忆路径)

    题意:就是说,给出一个三行三列的数组,其中元素为1--8和x,例如: 1 2 3 现在,需要你把它变成:1 2 3 要的最少步数的移动方案.可以右移r,左移l,上移u,下移dx 4 6 4 5 67 ...

  7. jdbc连接sqlserver报错java.lang.ClassNotFoundException: com.microsoft.jdbc.sqlserver.SQLServerDriver

    使用2008的数据库, 我已经引入的sqljdbc4的包,单还是报这个错,很奇怪突然想到在配置hibernate的时候,是拷贝下来的代码 然后到网上查了下, 因为是2008的版本驱动和2000的有点不 ...

  8. elasticsearch golang的sdk使用

    文档第一 <elasticsearch权威指南>直接看官网在线版的,比较新,网上那些pdf版的,都是2.x版的,许多不兼容 官方API手册,可以选择版本. golang sdk库的选择 主 ...

  9. nginx报502 bad GateWay错误的解决方法

    nginx+php-fpm+mysql的网站,访问nginx的某个页面,报502 GateWay的错误,一般见到此错误,可以判断是php-fpm的问题,而不是nginx的问题.通过监控nginx的错误 ...

  10. ViewController之间的转场和数据传递

    ViewController之间的转场和数据传递 可以正向传递值, 反向传递值. 注意反向传值的时候,方法的位置: https://github.com/urmyfaith/GRDBUsage/blo ...