提高代码效率的6个Python内存优化技巧

Python 优化内存管理 Python 作为一种动态类型编程语言,在 OOP 方面有更大的灵活性。 阅读详情

当项目变得越来越大时,有效地管理计算资源是一个不可避免的需求。Python与C或c++等低级语言相比,似乎不够节省内存。

但是其实有许多方法可以显著优化Python程序的内存使用,这些方法可能在实际应用中并没有人注意,所以本文将重点介绍Python的内置机制,掌握它们将大大提高Python编程技能。

在这里插入图片描述

首先在进行内存优化之前,我们首先要查看内存的使用情况

分配了多少内存?

有几种方法可以在Python中获取对象的大小。可以使用sys.getsizeof()来获取对象的确切大小,使用objgraph.show_refs()来可视化对象的结构,或者使用psutil.Process().memory_info()。RSS获取当前分配的所有内存。

 >>> import numpy as np
 >>> import sys
 >>> import objgraph
 >>> import psutil
 >>> import pandas as pd
 
 
 >>> ob = np.ones((1024, 1024, 1024, 3), dtype=np.uint8)
 
 ### Check object 'ob' size
 >>> sys.getsizeof(ob) / (1024 * 1024)
 3072.0001373291016
 
 ### Check current memory usage of whole process (include ob and installed packages, ...)
 >>> psutil.Process().memory_info().rss / (1024 * 1024)
 3234.19140625
 
 ### Check structure of 'ob' (Useful for class object)
 >>> objgraph.show_refs([ob], filename='sample-graph.png')
 
 ### Check memory for pandas.DataFrame
 >>> from sklearn.datasets import load_boston
 >>> data = load_boston()
 >>> data = pd.DataFrame(data['data'])
 >>> print(data.info(verbose=False, memory_usage='deep'))
 <class 'pandas.core.frame.DataFrame'>
 RangeIndex: 506 entries, 0 to 505
 Columns: 13 entries, 0 to 12
 dtypes: float64(13)
 memory usage: 51.5 KB
   
 ### Check memory for pandas.Series
 >>> data[0].memory_usage(deep=True)   # deep=True to include all the memory used by underlying parts that construct the pd.Series
 4176

这样我们才能根据对象的内存占用来查看实际的优化结果

slots

Python作为一种动态类型语言,在面向对象方面具有更大的灵活性。在运行时可以向Python类添加额外属性和方法的能力。

例如,下面的代码定义了一个名为Author的类。最初它有两个属性name和age。但是我们以后可以很容易地添加一个额外的job:

 class Author:
    def __init__(self, name, age):
        self.name = name
        self.age = age
 
 
 me = Author('Yang Zhou', 30)
 me.job = 'Software Engineer'
 print(me.job)
 # Software Engineer

但是这种灵活性在底层浪费了更多内存。

因为Python中每个类的实例都维护一个特殊的字典(dict)来存储实例变量。因为字典的底层基于哈希表的实现所以消耗了大量的内存。

在大多数情况下,我们不需要在运行时更改实例的变量或方法,并且__dict__不会(也不应该)在类定义后更改。所以Python为此提供了一个属性:slots。

它通过指定类的所有有效属性的名称来作为白名单:

 class Author:
    __slots__ = ('name', 'age')
 
    def __init__(self, name, age):
        self.name = name
        self.age = age
 
 
 me = Author('Yang Zhou', 30)
 me.job = 'Software Engineer'
 print(me.job)
 # AttributeError: 'Author' object has no attribute 'job'

白名单只定义了两个有效的属性name和age。由于属性是固定的,Python不需要为它维护字典,只为__slots__中定义的属性分配必要的内存空间。

下面我们做一个简单的比较:

 import sys
 
 
 class Author:
    def __init__(self, name, age):
        self.name = name
        self.age = age
 
 
 class AuthorWithSlots:
    __slots__ = ['name', 'age']
 
    def __init__(self, name, age):
        self.name = name
        self.age = age
 
 
 # Creating instances
 me = Author('Yang', 30)
 me_with_slots = AuthorWithSlots('Yang', 30)
 
 # Comparing memory usage
 memory_without_slots = sys.getsizeof(me) + sys.getsizeof(me.__dict__)
 memory_with_slots = sys.getsizeof(me_with_slots) # __slots__ classes don't have __dict__
 
 print(memory_without_slots, memory_with_slots)
 # 152 48
 print(me.__dict__)
 # {'name': 'Yang', 'age': 30}
 print(me_with_slots.__dict__)
 # AttributeError: 'AuthorWithSlots' object has no attribute '__dict__'

可以看到 152 和 48 明显节省了内存。

Generators

生成器是Python中列表的惰性求值版本。每当调用next()方法时生成一个项,而不是一次计算所有项。所以它们在处理大型数据集时非常节省内存。

 def number_generator():
    for i in range(100):
        yield i
 
 numbers = number_generator()
 print(numbers)
 # <generator object number_generator at 0x104a57e40>
 print(next(numbers))
 # 0
 print(next(numbers))
 # 1

上面的代码显示了一个编写和使用生成器的基本示例。关键字yield是生成器定义的核心。应用它意味着只有在调用next()方法时才会产生项i。

让我们比较一个生成器和一个列表,看看哪个更节省内存:

 mport sys
 
 numbers = []
 for i in range(100):
    numbers.append(i)
 
 def number_generator():
    for i in range(100):
        yield i
 
 numbers_generator = number_generator()
 print(sys.getsizeof(numbers_generator))
 # 112
 print(sys.getsizeof(numbers))
 # 920

可以看到使用生成器可以显著节省内存使用。如果我们将列表推导式的方括号转换成圆括号,它将成为生成器表达式。这是在Python中定义生成器的更简单的方法:

 import sys
 
 numbers = [i for i in range(100)]
 numbers_generator = (i for i in range(100))
 
 print(sys.getsizeof(numbers_generator))
 # 112
 print(sys.getsizeof(numbers))
 # 920

利用内存映射文件支持大文件处理

内存映射文件I/O,简称“mmap”,是一种操作系统级优化。

简单地说,当使用mmap技术对文件进行内存映射时,它直接在当前进程的虚拟内存空间中创建文件的映射,而不是将整个文件加载到内存中,这节省了大量内存。

Python已经提供了用于使用此技术的内置模块,因此我们可以轻松地利用它,而无需考虑操作系统级别的实现。

以下是如何在Python中使用mmap进行文件处理:

 import mmap
 
 
 with open('test.txt', "r+b") as f:
    # memory-map the file, size 0 means whole file
    with mmap.mmap(f.fileno(), 0) as mm:
        # read content via standard file methods
        print(mm.read())
        # read content via slice notation
        snippet = mm[0:10]
        print(snippet.decode('utf-8'))

Python使内存映射文件I/O技术的使用变得方便。我们所需要做的只是应用mmap.mmap()方法,然后使用标准文件方法甚至切片符号处理打开的对象。

选择适当的数据类型

开发人员应仔细而精确地选择数据类型。因为在某些情况下,使用一种数据类型比使用另一种数据类型更节省内存。

1、元组比列表更节省内存

元组是不可变的(在创建后不能更改),它允许Python在内存分配方面进行优化。列表是可变的,因此需要额外的空间来容纳潜在的修改。

 import sys
 
 my_tuple = (1, 2, 3, 4, 5)
 my_list = [1, 2, 3, 4, 5]
 
 print(sys.getsizeof(my_tuple))
 # 80
 print(sys.getsizeof(my_list))
 # 120

元组my_tuple比列表使用更少的内存,如果创建后不需要更改数据,我们应该选择元组而不是列表。

2、数组比列表更节省内存

Python中的数组要求元素具有相同的数据类型(例如,所有整数或所有浮点数),但列表可以存储不同类型的对象,这不可避免地需要更多的内存。如果列表的元素都是相同类型,使用数组会更节省内存:

 import sys
 import array
 
 my_list = [i for i in range(1000)]
 
 my_array = array.array('i', [i for i in range(1000)])
 
 print(sys.getsizeof(my_list))  
 # 8856
 print(sys.getsizeof(my_array))
 # 4064

另外:Python是数据科学的主导语言。有许多强大的第三方模块和工具提供更多的数据类型,如NumPy和Pandas。如果我们只需要一个简单的一维数字数组,而不需要NumPy提供的广泛功能,那么Python的内置数组是一个不错的选择。但当涉及到复杂的矩阵操作时,使用NumPy提供的数组是所有数据科学家的首选,也可能是最佳选择。

字符串驻留

看看下面的代码:

 >>> a = 'Y'*4096
 >>> b = 'Y'*4096
 >>> a is b
 True
 >>> c = 'Y'*4097
 >>> d = 'Y'*4097
 >>> c is d
 False

为什么a是b是真,而c是d是假呢?

这在Python中被称作字符串驻留(string interning).如果有几个值相同的小字符串,它们将被Python隐式地存储并在内存中并引用相同的对象。定义小字符串阈值数字是4096。

由于c和d的长度为4097,因此它们是内存中的两个对象而不是一个对象,不再隐式驻留字符串。所以当执行c = d时,我们得到一个False。

驻留是一种优化内存使用的强大技术。如果我们想要显式地使用它可以使用sys.intern()方法:

 >>> import sys
 >>> c = sys.intern('Y'*4097)
 >>> d = sys.intern('Y'*4097)
 >>> c is d
 True

关于Python学习指南

学好 Python 不论是就业还是做副业赚钱都不错,但要学会 Python 还是要有一个学习规划。最后给大家分享一份全套的 Python 学习资料,给那些想学习 Python 的小伙伴们一点帮助!

包括:Python激活码+安装包、Python web开发,Python爬虫,Python数据分析,人工智能、自动化办公等学习教程。带你从零基础系统性的学好Python!

👉Python所有方向的学习路线👈

Python所有方向路线就是把Python常用的技术点做整理,形成各个领域的知识点汇总,它的用处就在于,你可以按照上面的知识点去找对应的学习资源,保证自己学得较为全面。(全套教程文末领取)

在这里插入图片描述

👉Python学习视频600合集👈

观看零基础学习视频,看视频学习是最快捷也是最有效果的方式,跟着视频中老师的思路,从基础到深入,还是很容易入门的。

在这里插入图片描述

温馨提示:篇幅有限,已打包文件夹,获取方式在:文末

👉Python70个实战练手案例&源码👈

光学理论是没用的,要学会跟着一起敲,要动手实操,才能将自己的所学运用到实际当中去,这时候可以搞点实战案例来学习。

在这里插入图片描述

👉Python大厂面试资料👈

我们学习Python必然是为了找到高薪的工作,下面这些面试题是来自阿里、腾讯、字节等一线互联网大厂最新的面试资料,并且有阿里大佬给出了权威的解答,刷完这一套面试资料相信大家都能找到满意的工作。

在这里插入图片描述

在这里插入图片描述

👉Python副业兼职路线&方法👈

学好 Python 不论是就业还是做副业赚钱都不错,但要学会兼职接单还是要有一个学习规划。

在这里插入图片描述

👉 这份完整版的Python全套学习资料已经上传,朋友们如果需要可以扫描下方优快云官方认证二维码或者点击链接免费领取【保证100%免费】

内存不够用?Python优化内存利器 与列表、元组等容器类型不同的是,它们并不会把数据一次性读入内存,而是在需要使用时才生成数据。因此,当数据较大时,使用生成器和迭代器可以减少内存开销。在处理矩阵和表格等数据结构时,使用NumPy和Pandas能够优化内存使用。Python的垃圾回收机制会自动回收不再使用的内存。然而,有些大的对象可能需要更长时间才能被垃圾回收,从而占用了大量的内存。如何有效地优化Python内存?总之,Python中有许多优秀的工具可以帮助优化内存使用。比如,可以读取文件的部分数据进行处理,而不是一次性读取整个文件。 阅读详情

相关推荐

Python内存优化技巧:高效利用内存空间

优化Python代码的内存消耗是一个重要的任务,特别是在处理大数据集或需要处理大量数据时。内存映射文件允许将文件的内容映射到内存中,使你可以像访问内存一样访问文件的内容,而无需将整个文件加载到内存中。当处理大型数据集时,将数据分批处理可以显著减少内存消耗。相对于一次性加载整个数据集,将数据拆分为较小的块,逐个处理每个块,可以减少每个时间点在内存中所需的数据量。在处理大量数据时,及时释放不再需要的内存可以提高程序的内存利用率。是一个生成器表达式,它一次生成一个被处理过的行,而不是将所有行存储在内存中。

HackNebulaZ的博客 279

7个Python内存优化技巧,你用过几个?

当我们的项目变得越来越大时,高效管理计算资源是一个不可避免的要求。不幸的是,与低级语言如C或C++相比,Python在内存效率方面似乎不够。那么,现在应该更改编程语言吗?当然不是。事实上,有许多方法可以显著优化Python程序的内存使用,从优秀的模块和工具到先进的数据结构和算法。本文将聚焦于Python的内置机制,并介绍7个原始但有效的内存优化技巧。掌握这些技巧将显著提高我们的Python编程技能...

Warmer_Sweeter 2236

若依集成mybatisplus、兼容旧分页【亲测有效】

service类继承ServiceImpl类 实现 你的Service接口。hutool工具包和lombok工具包如果不需要的话可以自行删除并修改后面的类里面的代码。自带的pagehelper用的1.4.6里面的jsqlparser用的4.5.0。mybatis-plus用的3.4.2里面的jsqlparser用的4.0.0。jsqlparser包,不剔除是这样的,有个冲突,我用的前端写的请求,返回的格式和原来的一样,已兼容。你的Entity类上面需要增加表的名字。

lh155136的博客 3566

6个技巧帮你提高Python运行效率

随着国内对人工智能领域发展的大力支持,Python编程语言成为国内使用增长率的最大的编程语言。越来越多的人加入Python的学习行列,企业对Python的使用也越来越普遍。Python能够让你在端时间内通过少量代码,实现大量的操作。这里小编整理了6个Python编程技巧,帮你提高Python的运行效率。 对于CPU密集型的程序,可以使用multiprocessing的Process,Pool等封装好的类,通过多进程的方式实现并行计算。但是因为进程中的通信成本比较大,对于进程之间需要大量数据交互的程序效率未必

2401_84204207的博客 996

01 AUTOSAR CP标准文档阅读指南

01 AUTOSAR CP标准文档阅读指南

汽车软件工程师 | 好奇博主 | 处女座 1135

ABAP代码检查(Code Review)

1、SLIN 扩展程序检查 也可通过(SE38工具栏->检查-扩展程序检查) 进入 2、ATC 检查 通过<SE38菜单栏-检查-ABAP测试主控室> 或事物代码SCI, 支持自定义检查变式 SCI可以配置检查变式满足特殊需求,配置对象集用于批量检查 3、通过ABAP测试主控室实现统一管理,定期检查作业和监控功能(事务代码ATC) 参考 SLIN...

u012232542的博客 6072

提高代码效率的5个Python内存优化技巧

大家好,当项目变得越来越大时,有效地管理计算资源是一个不可避免的需求。Python与C或c++等低级语言相比,似乎不够节省内存。但是其实有许多方法可以显著优化Python程序的内存使用,这些方法可能在实际应用中并没有人注意,所以本文将重点介绍Python的内置机制,掌握它们将大大提高Python编程技能。首先在进行内存优化之前,我们首先要查看内存的使用情况。

csdn1561168266的博客 1117

【Unity引擎技术整合】 Unity学习路线 | 知识汇总 | 持续更新 | 保持乐趣 | 共同成长

本文对Unity引擎的知识进行了一个整理总结,基本包含了Unity中大部分的知识介绍。 网上也有很多Unity相关的学习资料,但大多数都不成体系,学起来的时候难免会东奔西走的摸不着头脑。 本文整理的多数文章都是有对应的系列性文章专栏,可以更方便的进行系统学习相关知识体系。

努力前行,总会成为自己心中的那道光 15万+

提高 Python 代码效率的 6 大技巧

Python是一门优秀的语言,它能让你在短时间内通过极少量代码就能完成许多操作。不仅如此,它还轻松支持多任务处理,比如多进程。 不喜欢Python的人经常会吐嘈Python运行太慢。但是,事实并非如此。作为程序猿就是希望如何优化代码,精简代码。今天就为大家精选6条python代码优化建议。 因为GIL的存在,Python很难充分利用多核CPU的优势。但是,可以通过内置的模块multiproce...

Nick.Peng's Blogs 1948

电磁场仿真软件:Sonnet_(12).Sonnet与其他软件的集成

Sonnet作为电磁场仿真领域的强大工具,不仅能够独立完成复杂的仿真任务,还可以通过与其他软件的集成,实现更高效的工作流程和更广泛的功能扩展。通过与CAD、EDA、数据处理软件、MATLAB、Python以及云计算平台的集成,Sonnet用户可以更好地利用现有设计资源,进行参数优化和结果分析,从而提升设计和仿真效率。希望本节的内容能够帮助你更好地理解和应用Sonnet的集成功能。

kkchenjj的博客 1432

基于3D相机的人体穴位识别与标注系统——完整Python实现方案

摘要 本文提出了一种基于3D相机的人体穴位识别与标注系统完整实现方案。系统采用Intel RealSense D435相机实时采集RGB-D数据,结合MediaPipe Pose模型进行人体33个关键骨骼点的三维姿态估计。通过建立穴位与骨骼关键点的映射关系,利用相机内参和深度信息将二维图像坐标转换为三维空间坐标。系统采用模块化设计,包含数据采集层、算法处理层、坐标转换层和可视化层,实现了穴位定位、三维坐标转换和点云可视化功能。关键技术包括:基于骨度折量法的穴位映射算法、深度图像到三维点云的转换方法,以及Op

AI的内部世界的博客 273

Python性能优化技巧:Profiling和Cython提高代码执行效率

性能优化是Python开发中的重要环节。通过Profiling工具,我们可以准确定位性能瓶颈,并针对这些瓶颈进行有针对性的优化。同时,使用Cython编译Python代码,特别是对于计算密集型任务,可以显著提高代码执行效率。结合Profiling和Cython这两种方法,可以使Python程序在保持开发效率的同时,最大程度地提高运行效率。在实际开发中,良好的设计和适当的优化手段相结合,能够使程序获得更好的性能表现。

萧鼎的博客 1585

Nuxt - 项目打包部署及上线到服务器流程(SSR 服务端渲染)

Nuxt-项目打包部署及上线到服务器流程,详细介绍Nuxt项目上线部署,服务端渲染(ssr)项目及nuxt项目部署过程,nuxt项目打包上线,Nuxt项目的部署教程,NuxtJS项目部署方案,Nuxt如何部署到线上,nuxt项目部署篇,Nuxt项目搭建到Nuxt项目部署,Nuxt项目从开始到部署,详细教程。服务器部署nuxt项目,nuxt服务端部署上线,在服务器上部署nuxt项目,NuxtJS项目——命令和部署。......

🏆 前端领域优质创作者 1万+

Python内存优化技巧

当您的项目规模越来越大时,高效管理内存资源就成为必然要求,本文将重点介绍 Python 的内置机制,并介绍 7 种原始但有效的内存优化技巧。掌握这些技巧将大大提高你的 Python 编程能力。

m0_75067840的博客 1613

神经影像和人类基因组关联分析的实践过程

现代全脑转录图谱为研究脑组织的分子相关性提供了前所未有的机会,可以使用无创神经成像进行量化。然而,将神经影像学数据与转录组测量相结合并不是直截了当的,需要仔细考虑才能做出有效的推断。在本文中,我们回顾了最近的研究工作,探讨了不同的方法选择如何影响成像转录组学分析的三个主要阶段,包括1)转录图谱数据的处理;2)将转录测量与独立衍生的神经影像学表型相关联;3)通过基因富集分析评估鉴定的关联的功能意义。我们的目标是为这个快速发展的领域促进标准化和可复制方法的发展。

从事脑科学核磁共振方法学研究,在Nature communications等权威期刊发表研究论文,熟练掌握磁共振处理方法和统计学方法,欢迎大家和我交流。 2203

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

6个Python内存条的优化小技巧

_slots__Python 作为一种动态类型编程语言,在 OOP 方面有更大的灵活性。在运行时向 Python 类中添加额外的属性和方法就是一个很好的例子。例如,下面的代码定义了一个名为 Author 的类。它最初有两个属性 name 和 age。然而,任何硬币都有两面。这种灵活性会浪费更多内存。因为 Python 中每个类的实例都会维护一个特殊的字典 (__dict__),用于存储实例变量。由于字典的底层是基于哈希表的实现,因此字典本身的内存效率很低,因此字典会消耗大量内存。

GLB_0627的博客 1102

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

Python 内存优化小技巧

_slots__Python 作为一种动态类型编程语言,在 OOP 方面有更大的灵活性。在运行时向 Python 类中添加额外的属性和方法就是一个很好的例子。例如,下面的代码定义了一个名为 Author 的类。它最初有两个属性 name 和 age。然而,任何硬币都有两面。这种灵活性会浪费更多内存。因为 Python 中每个类的实例都会维护一个特殊的字典 (__dict__),用于存储实例变量。由于字典的底层是基于哈希表的实现,因此字典本身的内存效率很低,因此字典会消耗大量内存。

2301_82000445的博客 1909

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

说说提高Python运行效率的技巧?

公众号新增加了一个栏目,就是每天给大家解答一道Python常见的面试题,反正每天不贪多,一天一题,正好合适,只希望这个面试栏目,给那些正在准备面试的同学,提供一点点帮助!...

522
上一篇: 使用Python shutil库进行文件和目录操作
下一篇: 使用Python检测贝叶斯网络的因果关系检测
普通网友
博客等级 码龄3年 4493粉丝 309原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值