(给机器学习算法与Python学习加星标,提升AI技能)
本文转自 | AI源创评论
原标题 | Memory Management in Python
作 者 | Jun Wu
翻 译 | 天字一号
审 校 | 唐里、Pita
对于软件开发人员而言,了解内存管理很重要。随着Python在软件开发中得到广泛使用,编写高效的Python代码通常意味着需要编写内存高效使用的代码。随着大数据的使用越来越广泛,内存管理的重要性不容忽视。无效的内存管理会导致应用程序和服务器端组件运行缓慢。内存泄漏通常会导致花费大量时间进行测试和调试,它还会严重破坏数据处理并引起并发处理问题。
即使大多数Python的内存管理都是由Python内存管理器完成的,但了解最佳编码实践以及Python的内存管理器的工作方式仍可以使代码更高效和可维护。
对于软件开发人员而言,内存管理最重要的部分是内存分配。了解在计算机的物理或虚拟内存中分配空白空间的过程至关重要。有两种类型的内存分配。
静态内存分配 - 程序在编译时分配了内存。例如在C / C ++中,您只能声明具有固定大小的静态数组。在编译时分配内存。堆栈用于实现静态分配。在这种情况下,不能重用内存。
1
static int a=
10
;

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

2
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。
不要这样:
1
mymsg=’line1’

2
mymsg+=’line2’
最好这样:
1
mymsg=[‘line1’,’line2 ]

2
‘’.join(mymsg)


 避免对字符串使用+运算

如果可以避免,请不要使用+运算符进行串联。由于字符串是不可变的,因此每次将元素添加到字符串时,Python都会创建一个新的字符串和一个新的地址。这意味着每次更改字符串时都需要分配新的内存。
不要这样做:
1msg=’hello’+mymsg+’world’
更好的选择:
1msg=’hello %s world’ % mymsg
 使用Generators
生成器允许您创建一个函数,一次返回一个项目,而不是一次返回所有项目。这意味着,如果您有大型数据集,则不必等待整个数据集都可以访问。
1def__iter__(self):
2return
 self._generator()

3
4def_generator(self):
5for
 itm 
in
 self.items():

6yield
 itm
 将评估置于循环之外
如果要遍历数据,则可以使用正则表达式的缓存版本。
1
match_regex=re.compile(“foo|bar”)

2
3for
 i 
in
 big_it:

4
     m = match_regex.search(i)

5
         ….
 将函数分配给局部变量
Python访问局部变量要比全局变量有效得多。将函数分配给局部变量,然后使用它们。
1
myLocalFunc=myObj.func

2for
 i 
in
 range(n):

3
    myLocalFunc(i)
 使用内置函数和库
尽可能使用内置函数和库。内置函数通常使用最佳内存使用方法来实现。
不要这样做:
1mylist=map(str.lower, oldlist)
与循环相比,使用关键字参数创建数据集的更好选择:
1
mycounter = Counter (a = 
1
, b = 
2
, c = 
3
, d = 
5
, e = 
6
, f = 
7
, g = 
8
)

2for
 i 
in
 mycounter.elements():

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

itertools(https://docs.python.org/3/library/itertools.html)为您节省了大量的循环时间。它还摆脱了代码的复杂性。
不要这样做:
1
mylist=[]

2for
 shape 
in
 [
True
False
]:

3for
 weight 
in
 (
1
5
):

4
          firstlist=firstlist+function(shape, weight)
最好这样:
1from
 itertools 
import
 product, chain

2
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对象的示例。因为它的元类一经定义便是单例设计模式,因此可以将其导入系统中的任何位置并再次定义,并且解释器将仅指向初始对象。它减少了内存占用并确保了安全性。不管团队中的其他开发人员多么初级,它们都不会导致重复的对象,从而防止它们更改系统某一部分中的命令,并防止另一部分中引用另一条命令。
1classSingleton(type):
2
    _instances = {} 

3def__call__(cls, *args, **kwargs):
4if
 cls 
notin
 cls._instances:

5
            cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs)

6return
 cls._instances[cls]

7
8classConfigDict(dict, metaclass=Singleton):
9def__init__(self):
10
        super().__init__(self.read_config_file())

11
12
    @staticmethod

13defread_config_file():
14
    “””

15
    Reads config file based on path passed when running app.

16
    :
return
: (dict) loaded data 
from
 yml file

17
    “””

18
19
    config_file_path = sys.argv[
-1
]

20ifnot
 config_file_path.endswith(“.yml”):

21raise
 ConfigDictError(message=”yml file 
not
 passed into flask app but {} instead”.format(config_file_path))

22return
 yaml.load(open(str(config_file_path)), Loader=yaml.FullLoader)


 如何检查Python代码的性能
您可以使用配置文件模块(例如cProfile和Profile:https://docs.python.org/3/library/profile.html)进行性能检查。
1python -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/)
继续阅读
阅读原文