Python内存管理机制
1、抛出一个问题:下面代码输出结果是什么?
list = [[]] * 5 list list[0].append(10) list list[1].append(20) list list.append(30) list
输出结果如下:
[[], [], [], [], []] [[10], [10], [10], [10], [10]] [[10, 20], [10, 20], [10, 20], [10, 20], [10, 20]] [[10, 20], [10, 20], [10, 20], [10, 20], [10, 20], 30]
第一行的输出结果直觉上很容易理解,就是创建了5个空列表。然而,不是创造一个包含五个独立列表的列表,而是对一个列表进行五次引用。
2、Python的内存管理机制
Python的内存管理截止可以从三个方面来讲
- 垃圾回收
- 引用计数
- 内存池机制
1)、垃圾回收
Python不像C++,Java等语言一样,他可以不用事先声明变量类型而直接对变量进行赋值。对于Python来讲,对象的类型和内存都是在运行时确定的。这也是Python语言为动态语言的原因。
2)、引用计数
Python采用了类似Windows内核对象一样的方式来对内存进行管理。每一个对象,都维护这一个对指向改对象的引用计数。

我们创建了一个对象10,然后这个整形对象的引用赋值给x,因为x是第一个引用,因此,这个整形对象的引用数为1。y=x创建了一个指向同一对象的引用别名y,并没有为y创建一个新的对象,而是将y也指向了x指向的整形对象,这样它的引用计数就为2。

我们可以看到x与y的id一直,这个id可以理解为变量在内存中的地址。
在Python中,变量相当于在内存中开辟了一块区域。当对一个对象进行赋值的时候,相当于将该变量引用到该对象上。此时,该变量的引用计数就是1。当有该变量被其他对象引用的时候引用计数加1。系统会自动维护这些标签,并定时扫描,当某标签的引用计数变为0的时候,就会被回收。
通过这个引用计数机制,我们可以联想到为什么Python中的字典复制问题

当y中的'machine'中的值被修改时,原始字典的内容也会被修改。
3)、内存池机制
Python的内存池机制为金字塔式结构,-1,-2层主要有操作系统进行操作,
第0层是C中的malloc,free等内存分配和释放函数进行操作;
第1层跟第2层是内存池,有Python的接口函数PyMem_Malloc函数实现,当对象小于256k时由该层直接分配内存;
第3层是最上层,也就是我们对Python对象的直接操作。
Python在这里主要干的工作有:
如果请求分配的内存在1~256字节之间就使用自己的内存管理系统,否则世界使用malloc。
这里还是会调用malloc分配内存,每次会分配一块大小为256k的大块内存。
经由内存池等级的内存到最后还是会回收到内存池,并不会调用C的free释放掉。以便下次使用。对于简单的Python对象,例如数值、字符串、元祖(tuple不可更爱)采用的是复制的方式,将对象B的变量赋值给对象A的时候,虽然A和B的内存空间仍相同,但当A的值发生变化时,会重新给A分配内存,此时A与B的地址将不在相同。

对于像字典(dict),列表(List)等,改变一个就会引起另一个的改变,称之为浅拷贝

注:
对于此文中的复制问题,可采用deepcopy函数来解决这个问题。
后续有待补充
posted on 2016-08-18 16:52 VersionBeathon 阅读(85) 评论(0) 收藏 举报
浙公网安备 33010602011771号