python使用yield来减少内存开销

原创 2016年01月17日 15:58:53

本文参考自:http://www.ibm.com/developerworks/cn/opensource/os-cn-python-yield/

以斐波那契数列的实现来说明这个问题:

demo1:

def fab(max): 
    n, a, b = 0, 0, 1 
    L = [] 
    while n < max: 
        L.append(b) 
        a, b = b, a + b 
        n = n + 1 
    return L
for n in fab(5):
     print n
一般来讲,我们都会写成上边程序的样子,这样既实现了基本功能,又可以复用,基本符合要求了。

但是如果max是1000w或者更大呢,那么存储在list中将会占据很大的内存。常见的情况还包括一下消耗大量内存的做法:

for line in open("test.txt").readlines(): 
    print line
#这种做法是将文件的中的内容一次全部读取到内存中,每次从内存中取出一行然后输出,如果文件内容太大,将消耗大量的内存。
for line in open("test.txt"):
     print line
#这种做好就好多了,既简单又不节省内存,利用迭代器来每次读取一行数据。
for i in range(1000): pass
#会产生一个1000个元素的list
for i in xrange(1000): pass
#xrange()产生的是一个迭代对象,而不是一个1000个元素的list, 每次迭代返回下一个数值 
上面两个小对比,是我们平时写程序时不是很注意的地方,但是当你读到这之后,以后写程序不光要考虑怎么实现,而且要写出更优秀的代码来。

然后继续我们的斐波那契数列:

demo2:

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

<pre class="displaycode">for n in Fab(5): 
    print n 


上面这个版本基本达到了我们的要求,实现基本功能+节省内存,利用函数next来实现每次输出下一个值, 但是这么小小的一个功能我们竟然写了这么多的代码,不够简洁!!!

demo3:

def fab(max): 
    n, a, b = 0, 0, 1 
    while n < max: 
        yield b 
        a, b = b, a + b 
        n = n + 1 
<pre name="code" class="python"><pre class="displaycode">for n in fab(5): 
    print n 


简单来讲:yield 的作用就是把一个函数变成一个 generator,带有 yield 的函数不再是一个普通函数,Python 解释器会将其视为一个 generator,调用 fab(5) 不会执行 fab 函数,而是返回一个 iterable 对象!在 for 循环执行时,每次循环都会执行 fab 函数内部的代码,执行到 yield b 时,fab 函数就返回一个迭代值,下次迭代时,代码从 yield b 的下一条语句继续执行,而函数的本地变量看起来和上次中断执行前是完全一样的,于是函数继续执行,直到再次遇到
 yield。(照抄的参考文章)

个人理解: 是不是就是实时调用的意思,什么时候执行next什么时候执行一次fab函数,但是上一次的值都在内存中存储。而不是一次将所有的结果求出放在list中。

更多细节请参考本文一开头给出的文章链接, 下面我再补充一下关于迭代器和生成器的理解:

生成器:生成器(Generator)是创建迭代器的简单而强大的工具

迭代器:

    1、对于无法随机访问的数据结构(比如set)而言,迭代器是唯一的访问元素的方式

    2、它不要求你事先准备好整个迭代过程中所有的元素。迭代器仅仅在迭代至某个元素时才计算该元素,而在这之前或之后,元素可以不存在或者被销毁。这个特点使得它特别适合用于遍历一些巨大的或是无限的集合,比如几个G的文件,或是斐波那契数列等等。


具体的理解以及内部是如何工作的,大体可以参照:http://www.jb51.net/article/73939.htm

如果想更身体的了解迭代协议等内容,可以自行学习。










版权声明:本文为博主原创文章,未经博主允许不得转载。

Python:用迭代器和生成器降低程序内存占用率

情况描述:用一个30行代码的python文件,处理300M的数据,用到的数据结构有:pandas.DataFrame(), list, dict,二重循环,处理完一次写入磁盘。 问题:内存占用率97%...
  • ztf312
  • ztf312
  • 2017年01月12日 09:54
  • 1635

Python小工具之消耗系统指定大小内存

Python小工具之消耗系统指定大小内存工作中需要根据某个应用程序具体吃了多少内存来决定执行某些操作,所以需要写个小工具来模拟应用程序使用内存情况,下面是我写的一个Python脚本的实现。#!/usr...
  • kongxx
  • kongxx
  • 2016年06月14日 08:51
  • 2618

Python 进程内存增长解决方案

作者简介: 张炎泼(XP) 白山云科技合伙人兼研发副总裁,绰号XP。 张炎泼先生于2016年加入白山云科技,主要负责对象存储研发、数据跨机房分布和修复问题解决等工作。以实现100PB...
  • BaishanCloud
  • BaishanCloud
  • 2017年07月31日 11:05
  • 349

一个减少多进程下python内存占用的小技巧

  在python中如果要使用fork或者multiprocess来做多进程,假如import的库很多或者很大,例如wxpython,查看各进程的内存占用你会发现两个进程的内存占用基本上相同,换句话说...
  • rockmen1
  • rockmen1
  • 2010年02月11日 12:05
  • 1900

Python 内存不释放原理

在maillist里面看到无数次的有人问,python速度为什么这么慢,python内存管理很差。实话说,我前面已经说过了。如果你在意内存/CPU,不要用python,改用C吧。就算C不行,起码也用个...
  • shaququ
  • shaququ
  • 2016年08月03日 09:27
  • 1441

如何手动释放Python的内存

在上篇博客中,提到了对一个脚本进行的多次优化。当时以为已经优化得差不多了,但是当测试人员测试时,我才发现,踩到了Python的一个大坑。 在上文的优化中,对每500个用户,会进行一些计算并记录结果在磁...
  • nirendao
  • nirendao
  • 2015年03月18日 22:24
  • 34774

os 面试题整理

一)请分别简单说一说进程和线程以及它们的区别。 进程是具有一定功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源调度和分配的一个独立单位。 线程是进程的实体,是CPU调度和分派的基...
  • sr_srr
  • sr_srr
  • 2018年02月10日 22:12
  • 4

python下generator等高级功能

python下使用argparse包来进行控制端的输入输入参数一个例子 import argparse def main(): parase = argparse.ArgumentParser...
  • on2way
  • on2way
  • 2017年04月24日 20:55
  • 2157

检测Python程序运行时间和内存占用的方法

很多时候,需要了解python程序的效率和内存使用情况,以便优化实现 。下面就是几种常用的方法。 1. 使用print 可以加载datetime模块,然后在需要的地方打印datetime....
  • davidchang365
  • davidchang365
  • 2017年01月18日 09:47
  • 2864

Python 对象内存占用

转自:http://www.cnblogs.com/Lvkun/archive/2012/03/01/python_object_memory_usage.html (github地址) ...
  • shanliangliuxing
  • shanliangliuxing
  • 2014年04月27日 23:06
  • 1004
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:python使用yield来减少内存开销
举报原因:
原因补充:

(最多只允许输入30个字)