我的编程空间,编程开发者的网络收藏夹
学习永远不晚

如何用Python代码减少Python所需的内存

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

如何用Python代码减少Python所需的内存

如何用Python代码减少Python所需的内存,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。

在执行程序时,如果内存中有大量活动的对象,就可能出现内存问题,尤其是在可用内存总量有限的情况下。在本文中,我们将讨论缩小对象的方法,大幅减少 Python 所需的内存。

如何用Python代码减少Python所需的内存

为了简便起见,我们以一个表示点的 Python 结构为例,它包括 x、y、z 坐标值,坐标值可以通过名称访问。

Dict

在小型程序中,特别是在脚本中,使用 Python 自带的 dict 来表示结构信息非常简单方便:

>>> ob = {'x':1, 'y':2, 'z':3}>>> x = ob['x']>>> ob['y'] = y

由于在 Python 3.6 中 dict 的实现采用了一组有序键,因此其结构更为紧凑,更深得人心。但是,让我们看看 dict 在内容中占用的空间大小:

>>> print(sys.getsizeof(ob))240

如上所示,dict 占用了大量内存,尤其是如果突然虚需要创建大量实例时:

如何用Python代码减少Python所需的内存

类实例

有些人希望将所有东西都封装到类中,他们更喜欢将结构定义为可以通过属性名访问的类:

class Point: # def __init__(self, x, y, z): self.x = x self.y = y self.z = z>>> ob = Point(1,2,3)>>> x = ob.x>>> ob.y = y

类实例的结构很有趣:

如何用Python代码减少Python所需的内存

在上表中,__weakref__ 是该列表的引用,称之为到该对象的弱引用(weak reference);字段 __dict__ 是该类的实例字典的引用,其中包含实例属性的值(注意在 64-bit 引用平台中占用 8 字节)。从 Python 3.3 开始,所有类实例的字典的键都存储在共享空间中。这样就减少了内存中实例的大小:

>>> print(sys.getsizeof(ob), sys.getsizeof(ob.__dict__)) 56 112

因此,大量类实例在内存中占用的空间少于常规字典(dict):

如何用Python代码减少Python所需的内存

不难看出,由于实例的字典很大,所以实例依然占用了大量内存。

带有 __slots__ 的类实例

为了大幅降低内存中类实例的大小,我们可以考虑干掉 __dict__ 和__weakref__。为此,我们可以借助 __slots__:

class Point: __slots__ = 'x', 'y', 'z' def __init__(self, x, y, z): self.x = x self.y = y self.z = z>>> ob = Point(1,2,3)>>> print(sys.getsizeof(ob))64

如此一来,内存中的对象就明显变小了:

如何用Python代码减少Python所需的内存

在类的定义中使用了 __slots__ 以后,大量实例占据的内存就明显减少了:

实例数

如何用Python代码减少Python所需的内存

目前,这是降低类实例占用内存的主要方式。

这种方式减少内存的原理为:在内存中,对象的标题后面存储的是对象的引用(即属性值),访问这些属性值可以使用类字典中的特殊描述符:

>>> pprint(Point.__dict__)mappingproxy( .................................... 'x': <member 'x' of 'Point' objects>, 'y': <member 'y' of 'Point' objects>, 'z': <member 'z' of 'Point' objects>})

为了自动化使用 __slots__ 创建类的过程,你可以使用库namedlist(https://pypi.org/project/namedlist)。namedlist.namedlist 函数可以创建带有 __slots__ 的类:

>>> Point = namedlist('Point', ('x', 'y', 'z'))

还有一个包 attrs(https://pypi.org/project/attrs),无论使用或不使用 __slots__ 都可以利用这个包自动创建类。

元组

Python 还有一个自带的元组(tuple)类型,代表不可修改的数据结构。元组是固定的结构或记录,但它不包含字段名称。你可以利用字段索引访问元组的字段。在创建元组实例时,元组的字段会一次性关联到值对象:

>>> ob = (1,2,3)>>> x = ob[0]>>> ob[1] = y # ERROR

元组实例非常紧凑:

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

由于内存中的元组还包含字段数,因此需要占据内存的 8 个字节,多于带有 __slots__ 的类:

如何用Python代码减少Python所需的内存

命名元组

由于元组的使用非常广泛,所以终有一天你需要通过名称访问元组。为了满足这种需求,你可以使用模块 collections.namedtuple。

namedtuple 函数可以自动生成这种类:

>>> Point = namedtuple('Point', ('x', 'y', 'z'))

如上代码创建了元组的子类,其中还定义了通过名称访问字段的描述符。对于上述示例,访问方式如下:

 class Point(tuple): # @property def _get_x(self): return self[0] @property def _get_y(self): return self[1] @property def _get_z(self): return self[2] # def __new__(cls, x, y, z): return tuple.__new__(cls, (x, y, z))

这种类所有的实例所占用的内存与元组完全相同。但大量的实例占用的内存也会稍稍多一些:

如何用Python代码减少Python所需的内存

记录类:不带循环 GC 的可变更命名元组

由于元组及其相应的命名元组类能够生成不可修改的对象,因此类似于 ob.x 的对象值不能再被赋予其他值,所以有时还需要可修改的命名元组。由于 Python 没有相当于元组且支持赋值的内置类型,因此人们想了许多办法。在这里我们讨论一下记录类(recordclass,https://pypi.org/project/recordclass),它在 StackoverFlow 上广受好评(https://stackoverflow.com/questions/29290359/existence-of-mutable-named-tuple-in)。

此外,它还可以将对象占用的内存量减少到与元组对象差不多的水平。

recordclass 包引入了类型 recordclass.mutabletuple,它几乎等价于元组,但它支持赋值。它会创建几乎与 namedtuple 完全一致的子类,但支持给属性赋新值(而不需要创建新的实例)。recordclass 函数与 namedtuple 函数类似,可以自动创建这些类:

 >>> Point = recordclass('Point', ('x', 'y', 'z')) >>> ob = Point(1, 2, 3)

类实例的结构也类似于 tuple,但没有 PyGC_Head:

如何用Python代码减少Python所需的内存

在默认情况下,recordclass 函数会创建一个类,该类不参与垃圾回收机制。一般来说,namedtuple 和 recordclass 都可以生成表示记录或简单数据结构(即非递归结构)的类。在 Python 中正确使用这二者不会造成循环引用。因此,recordclass 生成的类实例默认情况下不包含 PyGC_Head 片段(这个片段是支持循环垃圾回收机制的必需字段,或者更准确地说,在创建类的 PyTypeObject 结构中,flags 字段默认情况下不会设置 Py_TPFLAGS_HAVE_GC 标志)。

大量实例占用的内存量要小于带有 __slots__ 的类实例:

如何用Python代码减少Python所需的内存

dataobject

recordclass 库提出的另一个解决方案的基本想法为:内存结构采用与带 __slots__ 的类实例同样的结构,但不参与循环垃圾回收机制。这种类可以通过 recordclass.make_dataclass 函数生成:

>>> Point = make_dataclass('Point', ('x', 'y', 'z'))

这种方式创建的类默认会生成可修改的实例。

另一种方法是从 recordclass.dataobject 继承:

class Point(dataobject): x:int y:int z:int

这种方法创建的类实例不会参与循环垃圾回收机制。内存中实例的结构与带有 __slots__ 的类相同,但没有 PyGC_Head:

如何用Python代码减少Python所需的内存

>>> ob = Point(1,2,3)>>> print(sys.getsizeof(ob))40

如果想访问字段,则需要使用特殊的描述符来表示从对象开头算起的偏移量,其位置位于类字典内:

mappingproxy({'__new__': <staticmethod at 0x7f203c4e6be0>, ....................................... 'x': <recordclass.dataobject.dataslotgetset at 0x7f203c55c690>, 'y': <recordclass.dataobject.dataslotgetset at 0x7f203c55c670>, 'z': <recordclass.dataobject.dataslotgetset at 0x7f203c55c410>})

大量实例占用的内存量在 CPython 实现中是最小的:

如何用Python代码减少Python所需的内存

Cython

还有一个基于 Cython(https://cython.org/)的方案。该方案的优点是字段可以使用 C 语言的原子类型。访问字段的描述符可以通过纯 Python 创建。例如:

cdef class Python: cdef public int x, y, z def __init__(self, x, y, z): self.x = x self.y = y self.z = z

本例中实例占用的内存更小:

>>> ob = Point(1,2,3)>>> print(sys.getsizeof(ob))32

内存结构如下:

如何用Python代码减少Python所需的内存

大量副本所占用的内存量也很小:

如何用Python代码减少Python所需的内存

但是,需要记住在从 Python 代码访问时,每次访问都会引发 int 类型和 Python 对象之间的转换。

Numpy

使用拥有大量数据的多维数组或记录数组会占用大量内存。但是,为了有效地利用纯 Python 处理数据,你应该使用 Numpy 包提供的函数。

>>> Point = numpy.dtype(('x', numpy.int32), ('y', numpy.int32), ('z', numpy.int32)])

一个拥有 N 个元素、初始化成零的数组可以通过下面的函数创建:

 >>> points = numpy.zeros(N, dtype=Point)

内存占用是最小的:

如何用Python代码减少Python所需的内存

一般情况下,访问数组元素和行会引发 Python 对象与 C 语言 int 值之间的转换。如果从生成的数组中获取一行结果,其中包含一个元素,其内存就没那么紧凑了:

 >>> sys.getsizeof(points[0]) 68

因此,如上所述,在 Python 代码中需要使用 numpy 包提供的函数来处理数组。

看完上述内容是否对您有帮助呢?如果还想对相关知识有进一步的了解或阅读更多相关文章,请关注编程网行业资讯频道,感谢您对编程网的支持。

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

如何用Python代码减少Python所需的内存

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

如何用Python代码减少Python所需的内存

如何用Python代码减少Python所需的内存,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。在执行程序时,如果内存中有大量活动的对象,就可能出现内存问题,尤其
2023-06-02

python如何使用 __slots__ 减少内存开销

这篇文章将为大家详细讲解有关python如何使用 __slots__ 减少内存开销,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。使用 __slots__ 减少内存开销。你有没有观察到你的 Python 应
2023-06-27

Python高级技巧之怎么用一行代码减少一半内存占用

本篇内容介绍了“Python高级技巧之怎么用一行代码减少一半内存占用”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!图片的结果下面我来解释一下
2023-06-16

Python中如何用海象操作符减少重复代码

本篇文章给大家分享的是有关Python中如何用海象操作符减少重复代码,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。a = b是一条普通的赋值语句,读作a equals b,而a
2023-06-15

如何通过php函数来减少内存的使用?

在开发中,内存的使用是一个很重要的考量因素。如果在程序中使用大量的内存,可能会导致运行速度变慢甚至程序崩溃。因此,合理地管理和减少内存的使用是每个PHP开发者都应该关注的问题。本文将介绍一些通过PHP函数来减少内存使用的方法,并提供具体的代
2023-10-21

如何限制你的Python程序所能使用的内存

这篇文章主要讲解了“如何限制你的Python程序所能使用的内存”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“如何限制你的Python程序所能使用的内存”吧!如果程序开发不当,可能会出现占用过
2023-06-15

用python代码安装软件所需要的工具有哪些

这篇文章给大家介绍用python代码安装软件所需要的工具有哪些,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。今天我们的文章主要是介绍的是当我们把Python代码编写出来时,我们想在Python代码中安装一软件的过程中,
2023-06-17

如何限制你的Python程序所能使用的最大内存

这篇文章主要讲解了“如何限制你的Python程序所能使用的最大内存”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“如何限制你的Python程序所能使用的最大内存”吧!为了限制Python程序所
2023-06-15

如何使用Python中的内存管理技巧优化代码性能

如何使用Python中的内存管理技巧优化代码性能在编写Python代码时,优化性能是一个重要的考虑因素。虽然Python作为一种解释型语言,在运行效率上可能不如编译型语言,但是通过合理使用内存管理技巧,我们还是能够优化Python代码的性能
2023-10-22

如何优化Python占用的内存

概述如果程序处理的数据比较多、比较复杂,那么在程序运行的时候,会占用大量的内存,当内存占用到达一定的数值,程序就有可能被操作系统终止,特别是在限制程序所使用的内存大小的场景,更容易发生问题。下面我就给出几个优化Python占用内存的几个方法
2023-01-31

如何用Python增强Excel减少处理复杂数据的痛苦

今天就跟大家聊聊有关如何用Python增强Excel减少处理复杂数据的痛苦,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。Excel既是一种祝福,也是一种诅咒。当涉及到足够小的数据和足
2023-06-16

python如何计算执行特定代码所花费的时间

这篇文章主要为大家展示了“python如何计算执行特定代码所花费的时间”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“python如何计算执行特定代码所花费的时间”这篇文章吧。执行时间如下代码块可
2023-06-27

python中如何用天眼查询你所需的公司信息

本篇文章给大家分享的是有关python中如何用天眼查询你所需的公司信息,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。天眼可以查到所有公司的信息,以及它各种情况,下面就用接口的方
2023-06-02

如何用python代码爬取全国所有必胜客餐厅信息

如何用python代码爬取全国所有必胜客餐厅信息,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。当我刚接触 Python 时,我已经被 Python 深深所吸引。
2023-06-16

无需编写代码即可使用Python内置库的方法有哪些

本篇内容主要讲解“无需编写代码即可使用Python内置库的方法有哪些”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“无需编写代码即可使用Python内置库的方法有哪些”吧!1. Python CL
2023-07-06

如何使用python删除前面的代码

这期内容当中小编将会给大家带来有关如何使用python删除前面的代码,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。小型文件修改操作有一些通用的流程,删除文件的前n行,实际上也是对文件的修改,其中一个常用的
2023-06-15

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录