python是如何进行内存管理的?
3个方面:
1.垃圾回收:当引用计数为0时,或两个变量相互引用,但其本身为已经为0(独立的引用环)
2.引用计数:一个对象被创建时,就会创建一个引用计数。对象不再需要,且引用计数为0才会被垃圾回收
3.内存池机制:每个对象都有独立的内存池,且对象之间的内存池不相互引用,对象之间不共享内存池,
Python中所有小于256个字节的对象都使用pymalloc实现的分配器
******************************************************************************************************************************
引用计数:
python引用了一个机制:引用计数。
python内部使用引用计数,来保持追踪内存中的对象,Python内部记录了对象有多少个引用,及引用计数
在Python中,每个对象都有存有指向该对象的引用总数,即引用计数(reference count)。
我们可以使用sys包中的getrefcount(),来查看某个对象的引用计数。需要注意的是,当使用某个引用作为参数,
传递给getrefcount()时,参数实际上创建了一个临时的引用。因此,getrefcount()所得到的结果,会比期望的多1。
(引用减少)
某个对象的引用计数可能减少。比如,可以使用del关键字删除某个引用
del也可以用于删除容器元素中的元素
如果某个引用指向对象A,当这个引用被重新定向到某个其他对象B时,对象A的引用计数减少:
from sys import getrefcount
a = [1, 2, 3]
b = a
print(getrefcount(b))#3个
a = 1
print(getrefcount(b))#2个
(引用增加)
1.对象被创建:x=4
2.另外的别人被创建:y=x
3.被作为参数传递给函数:foo(x)
4.作为容器对象的一个元素:a=[1,x,'33']
变量更像是附在对象上的标签。当变量被绑定在一个对象上的时候,该变量的引用计数就是1
在Python中,每个对象都有存有指向该对象的引用总数,即引用计数(reference count)。
***************************************************************************************************************
对象的内存使用:
a=1
b=1
a is b :true
所有整数1的引用都指向同一对象。整数和短字符串使用赋值语句,也只是创造了新的引用,而不是对象本身
长的字符串和其它对象可以有多个相同的对象,可以使用赋值语句创建出新的对象。
对象引用对象:
Python的一个容器对象(container),比如表、词典等,可以包含多个对象。实际上,
容器对象中包含的并不是元素对象本身,是指向各个元素对象的引用。
*******************************************************************************
垃圾回收:
a.自动回收:
当Python运行时,会记录其中分配对象(object allocation)和取消分配对象(object deallocation)的次数。
当两者的差值高于某个阈值时,垃圾回收才会启动。
我们可以通过gc模块的get_threshold()方法,查看该阈值:
import gc
print(gc.get_threshold())
返回(700, 10, 10),后面的两个10是与分代回收相关的阈值,后面可以看到。700即是垃圾回收启动的阈值。
可以通过gc中的set_threshold()方法重新设置。
b.分代回收
Python将所有的对象分为0,1,2三代。所有的新建对象都是0代对象。当某一代对象经历过垃圾回收,依然存活,
那么它就被归入下一代对象。垃圾回收启动时,一定会扫描所有的0代对象。如果0代经过一定次数垃圾回收,
那么就启动对0代和1代的扫描清理。
当1代也经历了一定次数的垃圾回收后,那么会启动对0,1,2,即对所有对象进行扫描。
这两个次数即上面get_threshold()返回的(700, 10, 10)返回的两个10。也就是说,每10次0代垃圾回收,
会配合1次1代的垃圾回收;而每10次1代的垃圾回收,才会有1次的2代垃圾回收。
同样可以用set_threshold()来调整,比如对2代对象进行更频繁的扫描。
import gc
gc.set_threshold(700, 10, 5)
c.孤立的引用环
a = []
b = [a]
a.append(b)
del a
del b
上面我们先创建了两个表对象,并引用对方,构成一个引用环。删除了a,b引用之后,
这两个对象不可能再从程序中调用,就没有什么用处了。但是由于引用环的存在,
这两个对象的引用计数都没有降到0,不会被垃圾回收。
为了回收这样的引用环,Python复制每个对象的引用计数,可以记为gc_ref
参考:http://www.cnblogs.com/vamei/p/3232088.html