前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Python内存管理指南

Python内存管理指南

作者头像
AI研习社
发布2019-11-27 21:59:25
1.5K0
发布2019-11-27 21:59:25
举报
文章被收录于专栏:AI研习社AI研习社

原标题 | Memory Management in Python

作 者 | Jun Wu

翻 译 | 天字一号

审 校 | 唐里、Pita

对于软件开发人员而言,了解内存管理很重要。随着Python在软件开发中得到广泛使用,编写高效的Python代码通常意味着需要编写内存高效使用的代码。随着大数据的使用越来越广泛,内存管理的重要性不容忽视。无效的内存管理会导致应用程序和服务器端组件运行缓慢。内存泄漏通常会导致花费大量时间进行测试和调试,它还会严重破坏数据处理并引起并发处理问题。

即使大多数Python的内存管理都是由Python内存管理器完成的,但了解最佳编码实践以及Python的内存管理器的工作方式仍可以使代码更高效和可维护。

对于软件开发人员而言,内存管理最重要的部分是内存分配。了解在计算机的物理或虚拟内存中分配空白空间的过程至关重要。有两种类型的内存分配。

静态内存分配 - 程序在编译时分配了内存。例如在C / C ++中,您只能声明具有固定大小的静态数组。在编译时分配内存。堆栈用于实现静态分配。在这种情况下,不能重用内存。

代码语言:javascript
复制
static int a=10;

动态内存分配 - 在运行时为程序分配了内存。例如,在C / C ++中,您可以使用一元运算符new声明数组。内存在运行时分配。堆用于实现动态分配。在这种情况下,不需要时可以释放和重用内存。

代码语言:javascript
复制
int *p;
p=new int;

关于Python的好处是Python中的所有东西都是对象。这意味着动态内存分配是Python内存管理的基础。当不再需要对象时,Python内存管理器将自动从它们中回收内存。

Python是使用C编程语言实现的高级编程语言。Python内存管理器管理Python的内存分配。有一个私有heap,其中包含所有Python对象和数据结构。Python内存管理器按需管理Python堆。Python内存管理器具有特定于对象的分配器,可为int,string等特定对象分别分配内存。在此之下,原始内存分配器与操作系统的内存管理器进行交互,以确保私有堆上有空间。

Python内存管理器管理称为“块”的内存块。相同大小的块的集合构成了“池”。池是在Arenas上创建的,在堆= 64池上分配了256kB的内存块。如果对象被销毁,则内存管理器将用相同大小的新对象填充此空间。

方法和变量在堆栈存储器中创建。每当创建方法和变量时,都会创建一个堆栈框架。只要返回方法,这些框架就会自动销毁。

堆内存中创建对象和实例变量。一旦返回变量和函数,将对垃圾对象进行垃圾回收。

请务必注意,Python内存管理器不一定会将内存释放回操作系统,而是将内存返回给python解释器。Python有一个小的对象分配器,用于分配内存以供进一步使用。在长时间运行的进程中,您可能有未使用内存的增量保留。

使用联接将项目添加到列表是高效Python代码的最佳做法

无需将line1,line2分别添加到mymsg,而是使用list和join。

不要这样:

代码语言:javascript
复制
mymsg=’line1\n’
mymsg+=’line2\n’

最好这样:

代码语言:javascript
复制
mymsg=[‘line1’,’line2']
‘\n’.join(mymsg)

避免对字符串使用+运算

如果可以避免,请不要使用+运算符进行串联。由于字符串是不可变的,因此每次将元素添加到字符串时,Python都会创建一个新的字符串和一个新的地址。这意味着每次更改字符串时都需要分配新的内存。

不要这样做:

代码语言:javascript
复制
msg=’hello’+mymsg+’world’

更好的选择:

代码语言:javascript
复制
msg=’hello %s world’ % mymsg

使用Generators

生成器允许您创建一个函数,一次返回一个项目,而不是一次返回所有项目。这意味着,如果您有大型数据集,则不必等待整个数据集都可以访问。

代码语言:javascript
复制
def __iter__(self):
     return self._generator()

def _generator(self):
     for itm in self.items():
         yield itm

将评估置于循环之外

如果要遍历数据,则可以使用正则表达式的缓存版本。

代码语言:javascript
复制
match_regex=re.compile(“foo|bar”)

for i in big_it:
     m = match_regex.search(i)
         ….

将函数分配给局部变量

Python访问局部变量要比全局变量有效得多。将函数分配给局部变量,然后使用它们。

代码语言:javascript
复制
myLocalFunc=myObj.func
for i in range(n):
    myLocalFunc(i)

使用内置函数和库

尽可能使用内置函数和库。内置函数通常使用最佳内存使用方法来实现。

不要这样做:

代码语言:javascript
复制
mylist=map(str.lower, oldlist)

与循环相比,使用关键字参数创建数据集的更好选择:

代码语言:javascript
复制
mycounter = Counter (a = 1, b = 2, c = 3, d = 5, e = 6, f = 7, g = 8)
for i in mycounter.elements()

通过使用itertools摆脱不必要的循环

itertools(https://docs.python.org/3/library/itertools.html)为您节省了大量的循环时间。它还摆脱了代码的复杂性。

不要这样做:

代码语言:javascript
复制
mylist=[]
for shape in [True, False]:
     for weight in (1, 5):
          firstlist=firstlist+function(shape, weight)

最好这样:

代码语言:javascript
复制
from itertools import product, chain
list(chain.from_iterable(function(shape, weight) for weight, shape in product([True, False], range(1, 5))))

覆盖_new_并利用元类来进行安全和内存管理——作者@maxwell flitton

重写_new_并利用元类进行安全和内存管理,方法是@maxwell flitton 在执行Singleton和Flyweight模式时,重写__new__并利用元类对内存管理也非常有用和安全。例如,这是一个读取Yaml文件的dict对象的示例。因为它的元类一经定义便是单例设计模式,因此可以将其导入系统中的任何位置并再次定义,并且解释器将仅指向初始对象。它减少了内存占用并确保了安全性。不管团队中的其他开发人员多么初级,它们都不会导致重复的对象,从而防止它们更改系统某一部分中的命令,并防止另一部分中引用另一条命令。

代码语言:javascript
复制
class Singleton(type): 
_instances = {} 
 def __call__(cls, *args, **kwargs):
 if cls not in cls._instances:
 cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs)
 return cls._instances[cls]

class ConfigDict(dict, metaclass=Singleton):
 def __init__(self):
 super().__init__(self.read_config_file())

 @staticmethod
 def read_config_file():
 “””
 Reads config file based on path passed when running app.

 :return: (dict) loaded data from yml file
 “””
 config_file_path = sys.argv[-1]
 if not config_file_path.endswith(“.yml”):
 raise ConfigDictError(message=”yml file not passed into flask app but {} instead”.format(config_file_path))
 return yaml.load(open(str(config_file_path)), Loader=yaml.FullLoader)

如何检查Python代码的性能

您可以使用配置文件模块(例如cProfile和Profile:https://docs.python.org/3/library/profile.html)进行性能检查。

代码语言:javascript
复制
python -m cProfile [-o output_file][-s sort_order](-m module | myscript.py)

阅读有关Python内存管理的更多信息,可查看以下资源:

  • 流利的Python:清晰,简洁,有效的编程(http://geni.us/xA2PP)
  • Python Cookbook:精通Python 3(http://geni.us/yAoO1S)
  • 真正的Python:Python中的内存管理(https://realpython.com/python-memory-management/)
  • Python.org内存管理(https://docs.python.org/3/c-api/memory.html)
  • Atem Golubin:Python中的内存管理(https://rushter.com/blog/python-memory-managment/)
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-11-22,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 AI研习社 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 避免对字符串使用+运算
  • 通过使用itertools摆脱不必要的循环
  • 覆盖_new_并利用元类来进行安全和内存管理——作者@maxwell flitton
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档