python 迭代器和生成器详解
一、迭代器
说迭代器之前有两个相关的名词需要介绍:
可迭代对象:只要定义了__iter__()方法,我们就说该对象是可迭代对象,并且可迭代对象能提供迭代器。
迭代器:实现了__next__()或者next()(python2)方法的称为迭代器,迭代器仅仅在迭代到某个元素时才计算该元素,而在这之前或之后,元素可以不存在或者被销毁,因此只占用固定的内存。
迭代:当我们使用一个循环来遍历某个东西时,这个过程本身就叫迭代。迭代器迭代的元素只能往前不能后退。
1、为何用迭代器
下面用生成斐波那契数列为例子,说明为何用迭代器
- #代码1
- def fab(max):
- n, a, b = 0, 0, 1
- while n < max:
- print b
- a, b = b, a + b
- n = n + 1
- #直接在函数fab(max)中用print打印会导致函数的可复用性变差,因为fab返回None。其他函数无法获得fab函数返回的数列。
- #代码2
- def fab(max):
- L = []
- n, a, b = 0, 0, 1
- while n < max:
- L.append(b)
- a, b = b, a + b
- n = n + 1
- return L
- #代码2满足了可复用性的需求,但是占用了内存空间。
- #代码3,定义并使用迭代器
- class Fab(object):
- def __init__(self, max):
- self.max = max
- self.n, self.a, self.b = 0, 0, 1
- def __iter__(self):
- return self
- def next(self):
- if self.n < self.max:
- r = self.b
- self.a, self.b = self.b, self.a + self.b
- self.n = self.n + 1
- return r
- raise StopIteration()
- for key in Fabs(5):
- print key
- #Fabs 类通过 next() 不断返回数列的下一个数,内存占用始终为常数
2、如何使用迭代器
使用内建的工厂函数iter(iterable)可以获取迭代器对象(对象包含__iter__方法即可迭代,__iter__方法返回一个迭代器):
- >>> lst = range(5)
- >>> it = iter(lst)
- >>> it
- <listiterator object at 0x0000000001E43390>
使用next()方法访问下一个元素
- >>> it.next()
- 0
- >>> it.next()
- 1
- >>> it.next()
- 2
python处理迭代器越界是抛出StopIteration异常
- >>> it.next()
- 3
- >>> it.next
- <method-wrapper 'next' of listiterator object at 0x01A63110>
- >>> it.next()
- 4
- >>> it.next()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
了解了StopIteration,可以使用迭代器进行遍历了:
- lst = range(5)
- it = iter(lst)
- try:
- while True:
- val = it.next()
- print val
- except StopIteration:
- pass
3、for语法糖
幸运的是python提供的for语句语法糖为迭代提供了方便的使用方法。在for循环中,Python将自动调用工厂函数iter()获得迭代器,自动调用next()获取元素,还完成了检查StopIteration异常的工作。
- >>> lst = range(5)
- >>> for i in lst:
- ... print i
- ...
- 0
- 1
- 2
- 3
- 4
二、生成器
带有 yield 的函数在 Python 中被称之为 generator(生成器),几个例子说明下(还是用生成斐波那契数列说明),可以看出代码3远没有代码1简洁,生成器(yield)既可以保持代码1的简洁性,又可以保持代码3的效果。
- #代码4
- def fab(max):
- n, a, b = 0, 0, 1
- while n < max:
- yield b
- a, b = b, a + b
- n = n+ 1
- #执行
- for n in fab(5):
- print n
- 1
- 1
- 2
- 3
- 5
生成器也是一种迭代器,简单地讲,yield 的作用就是把一个函数变成一个 generator,带有 yield 的函数不再是一个普通函数,Python 解释器会将其视为一个 generator,调用 fab(5) 不会执行 fab 函数,而是返回一个 iterable 对象!在 for 循环执行时,每次循环都会执行 fab 函数内部的代码,执行到 yield b 时,fab 函数就返回一个迭代值,下次迭代时,代码从 yield b 的下一条语句继续执行,而函数的本地变量看起来和上次中断执行前是完全一样的,于是函数继续执行,直到再次遇到 yield。看起来就好像一个函数在正常执行的过程中被 yield 中断了数次,每次中断都会通过 yield 返回当前的迭代值。
也可以手动调用 fab(5) 的 next() 方法(因为 fab(5) 是一个 generator 对象,该对象具有 next() 方法),这样我们就可以更清楚地看到 fab 的执行流程:
- >>> f = fab(3)
- >>> f.next()
- 1
- >>> f.next()
- 1
- >>> f.next()
- 2
- >>> f.next()
- Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
return作用
在一个生成器中,如果没有return,则默认执行到函数完毕;如果遇到return,如果在执行过程中 return,则直接抛出 StopIteration 终止迭代。例如
- def read_file(fpath):
- BLOCK_SIZE = 1024
- with open(fpath, 'rb') as f:
- while True:
- block = f.read(BLOCK_SIZE)
- if block:
- yield block
- else:
- return
如果直接对文件对象调用 read() 方法,会导致不可预测的内存占用。好的方法是利用固定长度的缓冲区来不断读取文件内容。通过 yield,我们不再需要编写读文件的迭代类,就可以轻松实现文件读取。
python 迭代器和生成器详解的更多相关文章
- python迭代器与生成器详解
迭代器与生成器 迭代器(iterator)与生成器(generator)是 Python 中比较常用又很容易混淆的两个概念,今天就把它们梳理一遍,并举一些常用的例子. for 语句与可迭代对象(ite ...
- python设计模式之迭代器与生成器详解(五)
前言 迭代器是设计模式中的一种行为模式,它提供一种方法顺序访问一个聚合对象中各个元素, 而又不需暴露该对象的内部表示.python提倡使用生成器,生成器也是迭代器的一种. 系列文章 python设计模 ...
- python编程系列---可迭代对象,迭代器和生成器详解
一.三者在代码上的特征 1.有__iter__方法的对象就是可迭代类(对象) 2.有__iter__方法,__next()方法的对象就是迭代器3.生成器 == 函数+yield 生成器属于迭代器, 迭 ...
- [js高手之路] es6系列教程 - 迭代器与生成器详解
什么是迭代器? 迭代器是一种特殊对象,这种对象具有以下特点: 1,所有对象都有一个next方法 2,每次调用next方法,都会返回一个对象,该对象包含两个属性,一个是value, 表示下一个将要返回的 ...
- python操作redis用法详解
python操作redis用法详解 转载地址 1.redis连接 redis提供两个类Redis和StrictRedis用于实现Redis的命令,StrictRedis用于实现大部分官方的命令,并使用 ...
- python之OS模块详解
python之OS模块详解 ^_^,步入第二个模块世界----->OS 常见函数列表 os.sep:取代操作系统特定的路径分隔符 os.name:指示你正在使用的工作平台.比如对于Windows ...
- python之sys模块详解
python之sys模块详解 sys模块功能多,我们这里介绍一些比较实用的功能,相信你会喜欢的,和我一起走进python的模块吧! sys模块的常见函数列表 sys.argv: 实现从程序外部向程序传 ...
- python中threading模块详解(一)
python中threading模块详解(一) 来源 http://blog.chinaunix.net/uid-27571599-id-3484048.html threading提供了一个比thr ...
- Python数据类型及其方法详解
Python数据类型及其方法详解 我们在学习编程语言的时候,都会遇到数据类型,这种看着很基础也不显眼的东西,却是很重要,本文介绍了python的数据类型,并就每种数据类型的方法作出了详细的描述,可供知 ...
随机推荐
- 「CH2201」小猫爬山 解题报告
CH2201 小猫爬山 背景 Freda和rainbow饲养了N只小猫,这天,小猫们要去爬山.经历了千辛万苦,小猫们终于爬上了山顶,但是疲倦的它们再也不想徒步走下山了(呜咕>_<). 描述 ...
- PythonI/O进阶学习笔记_9.python的生成器
content: 1. 什么是生成器 2. 生成器的实现 3. 生成器的应用 一.生成器简介 1.什么是生成器 在 Python 中,使用了 yield 的函数被称为生成器(genera ...
- Excel获取当前日期和时间
在Excel中获取当前时间 1.第一种在空的单元格内输入函数“NOW()”回车即可获取当前时间如图 2.第二种选中空单元格“按住CTRL+:”回车即可获取当前时间 3.第一种在空的单元格内输入函数“t ...
- LinkedHashMap与HashMap的使用比较
现在由于项目需要,使用了LinkedHashMap,一开始由于很少用到Map,然后就直接使用了HashMap,在将数据成功存入之后取出来就出了问题,数据输出顺序没有按预期顺序输出,现在先看代码: 文件 ...
- 【转】7本免费的Java电子书和教程
本文由 ImportNew - 唐小娟 翻译自 Javapapers.如需转载本文,请先参见文章末尾处的转载要求. 1. Thinking in Java (Third Edition) 本书的作者是 ...
- JS怎样做四舍五入
1 .tofixed方法 toFixed() 方法可把 Number 四舍五入为指定小数位数的数字.例如将数据Num保留2位小数,则表示为:toFixed(Num):但是其四舍五入的规则与数学中的规则 ...
- WIN10升级后输入法无法输入中文
查看是否安装了中文输入法,可能在升级后用户文件出现问题. 在设置>语言.添加一下中文输入法.
- python 条件判断的三元表达式
示例:求两数中最大者 在JavaScript中代码如下: x = 1; y = 2; console.log(x > y ? x : y) 在python中代码如下: # 条件为真时的返回结果 ...
- Node: 使用nrm管理npm源
一.简介 npm是一款非常好用的包管理工具,在前端开发中很多时候都会使用npm安装其他包文件.但是,npm安装某些包时有时会安装地很慢,这是因为npm管理的源中有些是国外的,包下载的时候需要花费很多时 ...
- rdlc报表输入中文出现小方块
在用vs自带的报表文件的时候,在输入中文的时候,会出现一些小方块. 百度到的资料:当然我试了下,没有用. 用文本编辑器(我用的是editplus)打开需要批量处理的rdlc文件. 将所有 <St ...