Python效率低!

Python占内存!

Python太差劲!

...

作为近年来最为火热的编程语言之一,Python受到的争议和推崇同样很多。

无论是否从事Python方向的开发,都已经习惯把问题当做客观因素推卸给Python。

“你这个项目为什么耗时那么长?”

“Python的原因。”

我想说,Python为很多开发者背太多锅了。

的确,对比于C/C++、Java这些基于编译的语言而言,Python在内存利用和执行效率方面的确没有可比性。但是,它也没有大多数描述的那么不堪。

或许,有很多同学会想,至于为了一点一点内存费这么大劲吗?

至于!

举个例子,外出消费的过程中,觉得每次花费5块、10块不起眼,无关痛痒,但是每次月底还花呗的时候才发现居然消费了几千。

开发也一样,也许1个实例之间只节省了50byte,但是,100000000个呢?那就会节省高达5G的内存!

本文就来逐步介绍Python在内存方面的优惠,让你通过一篇文章迅速从青铜变成王者!

字典

字典对于Python就如同一把双刃剑。

字典在Python中要远比在Java、C++中占据更高的地位。在Python中,字典以其易于创建、删除、修改、读取,使得它备受欢迎。

我看过很多周围同事和GitHub开源代码,字典在Python中的使用频率非常之高。

但是,很多人却忽略了,字典具有很明显的弊端--耗内存

甚至很多从事多年Python开发的程序员也没有意识到这个问题,或者寻求替代方案。

下面来看一个例子,

>>> exm = {"x": 1, "y": 2, "z": 3}>>> print(sys.getsizeof(exm))240

直接使用字典,占用内存240byte

很多开发者已经习惯了使用Python字典,或者对前面提到的240byte没有什么概念。

那么,下面用类的方式来存储数据。这种方式在很多开源的Java、C++代码中非常常见。

下面来用用类实现以下等同字典的结构,

class Shape:def __init__(self, x, y, z):        self.x = x        self.y = y        self.z = z

exm = Shape(1, 2, 3)

这样的话exm.x的功能等同于字典中的exm["x"],可以用于访问对应的数据。

下面来看一下它占的内存,

>>> print(sys.getsizeof(exm) + sys.getsizeof(exm.__dict__))168

通过实现类,1个实例可以比字典节省72byte的内存!

通过字典的方式是类方式内存占用的1.4倍。

由于在Python类中,会用__dict__存储类的属性值,因此,内存占据比重较大。这里168byte内存,其中56byte来自exm实例,112byte来自__dict__

namedtuple

Python中常用的数据结构除了字典,还有元组tuple。

元组虽然可以用于存储数据,而且,可以通过索引进行取值,来替代通过key进行取值,但是它不具有键值信息。我想很多使用字典的场景,都是因为喜欢Python字典中key-value键值对,使得取值更加方便。

其实Python内置的collections提供了namedtuple可以替代字典的功能。

from collections import namedtuple

Shape = namedtuple('Shape', ['x', 'y', 'z'])

exm = Shape(1, 2, 3)

这样,我们可以通过exm.x进行取值,下面来看一下它的内存占用情况。

>>> print(sys.getsizeof(exm))72

相比于类实现的方法,namedtuple节省了96byte,相对于字典,它更是节省了高达168byte

通过字典的方式是namedtuple内存占用的3.3倍。

__slots__

__slots__是在Python内存优化中用的相对较多的方式,它相对于前面介绍的类实现方式__slots__能够确定性的指明哪些类属性可以访问,同时不需要__dict__去存储类属性的值,所以,对比于单纯的类实现形式能够进一步优化内存。

class Shape:

   __slots__ = 'x', 'y', 'z'

def __init__(self, x, y, z):      self.x = x       self.y = y       self.z = z

exm = Shape(1, 2, 3)

下面来看一下它的内存占用,

>>> print(sys.getsizeof(exm))64

相对于字典,它更是节省了高达176byte

通过字典的方式是namedtuple内存占用的3.8倍。

recordclass

前面介绍的方法都是通过Python内置的方法或模块实现的,现在再来介绍一种通过第三方包实现内存优化的方式。

recordclass包引入了recordclass.mutabletuple类型,该类型与元组tuple几乎相同,但它支持赋值。在此基础上,创建的子类几乎与namedtuples完全相同,但支持将新值分配给字段(无需创建新实例)。

from recordclass import recordclass

Shape = recordclass('Shape', ('x', 'y', 'z'))

exm = Shape(1, 2, 3)print(exm.x)

下面来看一下它的内存占用情况,

>>> print(sys.getsizeof(exm))48

相对于字典,它更是节省了高达192byte

通过字典的方式是namedtuple内存占用的5倍。

Dataclass

recordclass还提供了另外一种更加节省内存的解决方案。

在内存中使用与具有__slots__的类实例中相同的存储结构,但不参与循环垃圾回收机制。

from recordclass import make_dataclass

Shape = make_dataclass('Shape', ('x', 'y', 'z'))

exm = Shape(1, 2, 3)print(exm.x)

下面来看一下内存占用情况,

>>> print(sys.getsizeof(exm))40

相对于字典,它更是节省了高达200byte

通过字典的方式是namedtuple内存占用的6倍。

Cython

最后一种方式,采用Cython

Cython 是具有 C 数据类型的 Python,因此,参数和变量都可以声明为C 数据类型,在内存上能够进一步优化。

不过,采用Cython方式要比前面几种方式更为复杂一些。首先需要把核心逻辑写在.pyx文件中,然后需要进行编译成.so或者.pyd文件。最后,在另一个Python文件中通过import导入模块。

下面来看一下示例,

# Example.pyx

cdef class Shape:  cdef public int x, y, z

def __init__(self, x, y, z):       self.x = x       self.y = y       self.z = z

然后,写一下编译文件,

# setup.py

from distutils.core import setupfrom Cython.Build import cythonizesetup(    ext_modules = cythonize("cc.pyx"))

在命令行下执行setup.py,编译文件,

$ python setup.py build_ext --inplace

在Windows下会生成一个Shape.pyd文件,在Linux和macOS下会生成Shape.so文件。这里只是介绍一下,对于使用无关紧要。

然后就是调用编译后的文件。

import Shapeexm = Shape(1, 2, 3)print(exm.x)

下面来看一下它的内存占用情况,

>>> print(sys.getsizeof(exm))32

相对于字典,它更是节省了高达208byte

通过字典的方式是namedtuple内存占用的7.5倍。

不积跬步,无以至千里。

在编程开发中也是这样,我们总是会觉得208byte微乎其微,对于现在计算机的内存来说无关紧要。或许,在一些财大气粗的公司、部门,动辄就可以提供一个集群让开发者使用。但是,内存是由上限的,不可能无节制的使用。但是,积少成多,在一个大工程中,数据量较大的项目中,如果进行这样的优化,内存优化是非常可观的。

以本文为例,很多Python开发者都已经习惯使用字典这种数据结构,并且对于内存占用不以为然。然而,你会发现,通过使用Cython,一个实例的内存可以从240byte优化到32byte,内存占用减少比例高达86.7%

推荐阅读

太赞了!《Python 黑魔法指南》终于面世了

深扒微信多开的秘密后,我竟然发现了个 bug

Python 为什么用 # 号作注释符?

太好玩了,看看我用 Pyecharts绘制的“时间轮播图”

Python 10 个习惯用法,看看你都知道不?

手绘10张图,把CSRF、JWT说得明明白白的

长按下图  ➡   关注博主

(按左边关注 Python, 按右边关注 Goalng)

内存占用_一文教你节省 90% 的内存占用相关推荐

  1. [转]从青铜到王者,一文教你节省90%内存占用

    作者:[七步编程]公众号 原文:在Python中应用枚举类,只需要这1个理由就够了! 专注Python.AI.大数据,请关注公众号[七步编程] Python效率低! Python占内存! Python ...

  2. mysql内存报警_[MySQL生产环境] Innodb存储引擎内存报警问题处理过程_MySQL

    bitsCN.com [MySQL生产环境] Innodb存储引擎内存报警问题处理过程 1 不停的收到email报警,内存值超过阀值80%了. 2 top下,mysqld进程确实占据了77.5%,再加 ...

  3. java thread 内存泄露_记一次ThreadLocal引发的内存泄露

    概念 ​首先解释下内存溢出和内存泄露的概念.内存溢出一般指的是out of memory,也就是我们经常说的OOM,常发生在堆,方法区和方法栈.内存泄露指的是一段程序在申请内存空间后,无法释放已经申请 ...

  4. python内存泄漏_诊断和修复Python中的内存泄漏

    python内存泄漏 Fugue uses Python extensively throughout the Conductor and in our support tools, due to i ...

  5. 写java线程导致电脑内存不足_如何写出让java虚拟机发生内存溢出异常OutOfMemoryError的代码...

    程序小白在写代码的过程中,经常会不经意间写出发生内存溢出异常的代码.很多时候这类异常如何产生的都傻傻弄不清楚,如果能故意写出让jvm发生内存溢出的代码,有时候看来也并非一件容易的事.最近通过学习< ...

  6. 降低代码执行中得内存消耗_微服务中使用 OpenJ9 JVM内存占用降低60%!

    专注于Java领域优质技术,欢迎关注 作者: 陈一乐 来自:陈一乐 随着微服务的普及,许多企业踏上微服务之旅. 微服务化后,应用数量可能高一个数量级.一般企业,以前三五个应用能支撑业务,微服务化之后应 ...

  7. mysql5.7内存占用_解决mysql升级到5.7内存占用过大问题

    背景 在只有512M内存的云主机中的mysql随着系统升级更新到5.7后,发现启动后啥都不干内存就占用到160M左右,大大超过之前的使用,这是怎么回事呢? 优化 经过查找资料,在mysql的配置文件中 ...

  8. python查看运行内存占用_利用Python如何实时检测自身内存占用

    前言 最近在做文本统计,用 Python 实现,遇到了一个比较有意思的难题--如何保存统计结果. 直接写入内存实在是放不下,十几个小时后内存耗尽,程序被迫关闭.如果直接写入数据库吧,每次写入又太慢了, ...

  9. java8堆内存模型_「GC系列」JVM堆内存分代模型及常见的垃圾回收器

    1. 内存分代模型 为什么要说JVM的内存分代模型呢,因为内存分代和垃圾回收器的运行是有关系的. 现在大部分用到的垃圾回收器在逻辑上是分代的,除了G1之外的其他垃圾回收器在逻辑上和物理上都是分代的. ...

  10. java的vps多大内存够用_如今电脑配多少G的内存,才真正够用?

    可能大家都知道,内存是CPU处理器与磁盘之间用于临时存储数据的设备,如果你电脑的内存过小,势必会影响电脑的运行速度,但现在大家都追求大内存,这个内存大到多少才合适呢? 每当有人向我寻求选购电脑的意见时 ...

最新文章

  1. python内置函数open_python_内置函数和open
  2. Go 语言编程 — gorm ORM 框架
  3. 工具SSHSecure连接远程服务器步骤
  4. Android RemoteController使用
  5. ie 7 beta 2出来了
  6. boost windows编译
  7. 阿里云DDoS高防 - 访问与攻击日志实时分析(四)
  8. python中ntlk报错及解决
  9. Chrome无法打开文件的错误 [Not allowed to load local resource: file://XXXX]
  10. Wine 1.5.15 发布
  11. shell 按文件每行长度排序
  12. 极简的js点击组图切换效果
  13. win10玩cf如何调全屏_穿越火线:WIN10系统烟雾头和画面卡顿解决办法
  14. 刷牙也有如此强大的“黑科技”?------艾优电动牙刷深度体验
  15. TM1668 与 CT1668 驱动有差异?
  16. 关于c++取绝对值的方法
  17. PAT-1014 福尔摩斯的约会
  18. vue前端导出excel,js-xlsx、xlsxStyle,可设置样式、表格合并;(包含获取excel列数函数、excel合并表格缺少边框处理函数)
  19. Java对dat文件内容进行查询_java读写dat文件
  20. uart_ops结构体分析之amba_pl011_pops

热门文章

  1. 【BZOJ】3289: Mato的文件管理(莫队算法+树状数组)
  2. IE css hack整理
  3. 数据库连接池的深入理解
  4. bzoj2530 [POI2011]Party
  5. Python结合selenium自动领取无忧币的脚本
  6. leetcode56. Merge Intervals
  7. iOS 疑难杂症 — — 推送本地国际化 loc-key 本地化失败的问题
  8. DNS-实验3_委派子域和转发
  9. Windows系统下各浏览器常用CSS hack汇总表图
  10. 每日小记2012.5.1