每天一点python —— 迭代器与生成器
2015-11-20 09:53
495 查看
迭代器
转自:http://www.cnblogs.com/huxi/archive/2011/07/01/2095931.html迭代器(Iterator)概述
迭代器是访问集合内元素的一种方式。迭代器对象从集合的第一个元素开始访问,直到所有的元素都被访问一遍后结束。
迭代器不能回退,只能往前进行迭代。这并不是什么很大的缺点,因为人们几乎不需要在迭代途中进行回退操作。
迭代器也不是线程安全的,在多线程环境中对可变集合使用迭代器是一个危险的操作。但如果小心谨慎,或者干脆贯彻函数式思想坚持使用不可变的集合,那这也不是什么大问题。
对于原生支持随机访问的数据结构(如tuple、list),迭代器和经典for循环的索引访问相比并无优势,反而丢失了索引值(可以使用内建函数enumerate()找回这个索引值,这是后话)。但对于无法随机访问的数据结构(比如set)而言,迭代器是唯一的访问元素的方式。
迭代器的另一个优点就是它不要求你事先准备好整个迭代过程中所有的元素。迭代器仅仅在迭代至某个元素时才计算该元素,而在这之前或之后,元素可以不存在或者被销毁。这个特点使得它特别适合用于遍历一些巨大的或是无限的集合,比如几个G的文件,或是斐波那契数列等等。这个特点被称为延迟计算或惰性求值(Lazy evaluation)。
迭代器更大的功劳是提供了一个统一的访问集合的接口。只要是实现了__iter__()方法的对象,就可以使用迭代器进行访问。
使用迭代器
使用内建的工厂函数iter(iterable)可以获取迭代器对象:
那么在这个例子中,我们已经访问到了最后一个元素1,再使用next()方法会怎样呢?
这种做法与迭代前手动检查是否越界相比各有优点。但Python的做法总有一些利用异常进行流程控制的嫌疑。
了解了这些情况以后,我们就能使用迭代器进行遍历了。
常用的几个内建数据结构tuple、list、set、dict都支持迭代器,字符串也可以使用迭代操作。你也可以自己实现一个迭代器,如上所述,只需要在类的__iter__方法中返回一个对象,这个对象拥有一个next()方法,这个方法能在恰当的时候抛出StopIteration异常即可。但是需要自己实现迭代器的时候不多,即使需要,使用生成器会更轻松。下一篇我们将讨论生成器的部分。
*异常并不是非抛出不可的,不抛出该异常的迭代器将进行无限迭代,某些情况下这样的迭代器很有用。这种情况下,你需要自己判断元素并中止,否则就死循环了!
使用迭代器的循环可以避开索引,但有时候我们还是需要索引来进行一些操作的。这时候内建函数enumerate就派上用场咯,它能在iter函数的结果前加上索引,以元组返回,用起来就像这样:
生成器表达式(Generator expression)和列表解析(List Comprehension)
绝大多数情况下,遍历一个集合都是为了对元素应用某个动作或是进行筛选。如果看过本文的第二部分,你应该还记得有内建函数map和filter提供了这些功能,但Python仍然为这些操作提供了语言级的支持。
你也可以为列表解析提供if子句进行筛选:
第一个问题是,因为对元素应用的动作太复杂,不能用一个表达式写出来,所以不使用列表解析。这是典型的思想没有转变的例子,如果我们将动作封装成函数,那不就是一个表达式了么?
第二个问题是,因为if子句里的条件需要计算,同时结果也需要进行同样的计算,不希望计算两遍,就像这样:
相关文章推荐
- ipythonnotebook + spark
- Python获取操作系统信息(版本、操作系统名称、位数、架构等)
- python基础之各种异常及其解决方案
- 使用python实现短语查询
- python 能干什么
- python3.x 对 python2.x 语法变动
- Python基础(3)
- Python学习 - 基础入门(1)
- 我的python第三天
- python-excel的模块xlrd和xlwt用法及注意事项整理
- Python(1)
- Python实现将xml导入至excel
- Python聚类算法之基本K均值实例详解
- Python聚类算法之凝聚层次聚类实例分析
- Python聚类算法之DBSACN实例分析
- 将Emacs打造成强大的Python代码编辑工具
- Windows上配置Emacs来开发Python及用Python扩展Emacs
- 详解Python编程中time模块的使用
- 在Mac OS系统上安装Python的Pillow库的教程
- Python编程中使用Pillow来处理图像的基础教程