一、迭代器

说迭代器之前有两个相关的名词需要介绍:
可迭代对象:只要定义了__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 迭代器和生成器详解的更多相关文章

  1. python迭代器与生成器详解

    迭代器与生成器 迭代器(iterator)与生成器(generator)是 Python 中比较常用又很容易混淆的两个概念,今天就把它们梳理一遍,并举一些常用的例子. for 语句与可迭代对象(ite ...

  2. python设计模式之迭代器与生成器详解(五)

    前言 迭代器是设计模式中的一种行为模式,它提供一种方法顺序访问一个聚合对象中各个元素, 而又不需暴露该对象的内部表示.python提倡使用生成器,生成器也是迭代器的一种. 系列文章 python设计模 ...

  3. python编程系列---可迭代对象,迭代器和生成器详解

    一.三者在代码上的特征 1.有__iter__方法的对象就是可迭代类(对象) 2.有__iter__方法,__next()方法的对象就是迭代器3.生成器 == 函数+yield 生成器属于迭代器, 迭 ...

  4. [js高手之路] es6系列教程 - 迭代器与生成器详解

    什么是迭代器? 迭代器是一种特殊对象,这种对象具有以下特点: 1,所有对象都有一个next方法 2,每次调用next方法,都会返回一个对象,该对象包含两个属性,一个是value, 表示下一个将要返回的 ...

  5. python操作redis用法详解

    python操作redis用法详解 转载地址 1.redis连接 redis提供两个类Redis和StrictRedis用于实现Redis的命令,StrictRedis用于实现大部分官方的命令,并使用 ...

  6. python之OS模块详解

    python之OS模块详解 ^_^,步入第二个模块世界----->OS 常见函数列表 os.sep:取代操作系统特定的路径分隔符 os.name:指示你正在使用的工作平台.比如对于Windows ...

  7. python之sys模块详解

    python之sys模块详解 sys模块功能多,我们这里介绍一些比较实用的功能,相信你会喜欢的,和我一起走进python的模块吧! sys模块的常见函数列表 sys.argv: 实现从程序外部向程序传 ...

  8. python中threading模块详解(一)

    python中threading模块详解(一) 来源 http://blog.chinaunix.net/uid-27571599-id-3484048.html threading提供了一个比thr ...

  9. Python数据类型及其方法详解

    Python数据类型及其方法详解 我们在学习编程语言的时候,都会遇到数据类型,这种看着很基础也不显眼的东西,却是很重要,本文介绍了python的数据类型,并就每种数据类型的方法作出了详细的描述,可供知 ...

随机推荐

  1. 基于CentOS 7 部署MySQL 5.7的基本操作

    关闭selinux # sed -i '/SELINUX/s/enforcing/disabled/' /etc/selinux/config重启后生效# sestatus 修改提示符配置# vi / ...

  2. 开源工具abaplint的介绍

    长期以来,SAP提供的标准ABAP开发工具是我们对代码进行检查的唯一方式.这意味着我们只能对ABAP服务器上的ABAP代码做出分析,而离线代码则成为了纯粹的文本,开发者无法对其进行检查.abaplin ...

  3. 前端面试基础回顾之深入JS继承

    前言 对于灵活的js而言,继承相比于java等语言,继承实现方式可谓百花齐放.方式的多样就意味着知识点繁多,当然也是面试时绕不开的点.撇开ES6 class不谈,传统的继承方式你知道几种?每种实现原理 ...

  4. 学以致用,react学习前奏准备阶段

    ReactJS:支持React开发,提供JSX代码提示,高亮显示,ReactJS官方介绍 1.cdm→  componentDidMount: fn() { ... }   cdm 2.cdup→  ...

  5. C# 获取WebBrowser内容的高度

    int webHeight =0; WebBrowser web =new WebBrowser(); web.Navigate("about:blank"); while (we ...

  6. 数据量不足,MedicalNet 如何助力医疗影像 AI 突破瓶颈?

    ​导读 |近日,云+社区技术沙龙“腾讯开源技术”圆满落幕.本次沙龙邀请了多位腾讯技术专家,深度揭秘了腾讯开源项目TencentOS tiny.TubeMQ.Kona JDK.TARS以及Medical ...

  7. 简述http协议及抓包分析

    1:HTTP请求头和响应头的格式 1:HTTP请求格式:<request-line><headers><blank line>[<request-body&g ...

  8. ORM基础2 字段及其参数和meta

    一.ORM简介 1.概念:ORM(Object Relational Mappingt ),对象关系映射 2.实质:类与数据库之间的映射 3.优点: 开发人员不用写数据库 4.缺点: 开发人员,数据库 ...

  9. windows下远程访问Linux系统中mysql

    1,查询MySQL数据库是否允许远程ip访问,命令如下: sql语句: use mysql; select host, user from user; 查询结果为127.0.0.1或者localhos ...

  10. python打包成可执行文件

    1 最开始我直接把在Windows上打包的run.exe文件上传到Linux以为可以直接用了.但是./run后报错.百度后知道,Windows上的程序不能在Linux上运行 Linux下文件是否可执行 ...