一.垃圾回收機(jī)制
Python中的垃圾回收是以引用計(jì)數(shù)為主,分代收集為輔。引用計(jì)數(shù)的缺陷是循環(huán)引用的問(wèn)題。
在Python中,如果一個(gè)對(duì)象的引用數(shù)為0,Python虛擬機(jī)就會(huì)回收這個(gè)對(duì)象的內(nèi)存。
#encoding=utf-8__author__ = 'kevinlu1010@qq.com' class ClassA(): def __init__(self): print 'object born,id:%s'%str(hex(id(self))) def __del__(self): print 'object del,id:%s'%str(hex(id(self))) def f1(): while True: c1=ClassA() del c1
執(zhí)行f1()會(huì)循環(huán)輸出這樣的結(jié)果,而且進(jìn)程占用的內(nèi)存基本不會(huì)變動(dòng)
object born,id:0x237cf58object del,id:0x237cf58
c1=ClassA()會(huì)創(chuàng)建一個(gè)對(duì)象,放在0x237cf58內(nèi)存中,c1變量指向這個(gè)內(nèi)存,這時(shí)候這個(gè)內(nèi)存的引用計(jì)數(shù)是1
del c1后,c1變量不再指向0x237cf58內(nèi)存,所以這塊內(nèi)存的引用計(jì)數(shù)減一,等于0,所以就銷(xiāo)毀了這個(gè)對(duì)象,然后釋放內(nèi)存。
導(dǎo)致引用計(jì)數(shù)+1的情況
對(duì)象被創(chuàng)建,例如a=23
對(duì)象被引用,例如b=a
對(duì)象被作為參數(shù),傳入到一個(gè)函數(shù)中,例如func(a)
對(duì)象作為一個(gè)元素,存儲(chǔ)在容器中,例如list1=[a,a]
導(dǎo)致引用計(jì)數(shù)-1的情況
對(duì)象的別名被顯式銷(xiāo)毀,例如del a
對(duì)象的別名被賦予新的對(duì)象,例如a=24
一個(gè)對(duì)象離開(kāi)它的作用域,例如f函數(shù)執(zhí)行完畢時(shí),func函數(shù)中的局部變量(全局變量不會(huì))
對(duì)象所在的容器被銷(xiāo)毀,或從容器中刪除對(duì)象
demo
def func(c,d): print 'in func function', sys.getrefcount(c) - 1 print 'init', sys.getrefcount(11) - 1a = 11print 'after a=11', sys.getrefcount(11) - 1b = aprint 'after b=1', sys.getrefcount(11) - 1func(11)print 'after func(a)', sys.getrefcount(11) - 1list1 = [a, 12, 14]print 'after list1=[a,12,14]', sys.getrefcount(11) - 1a=12print 'after a=12', sys.getrefcount(11) - 1del aprint 'after del a', sys.getrefcount(11) - 1del bprint 'after del b', sys.getrefcount(11) - 1# list1.pop(0)# print 'after pop list1',sys.getrefcount(11)-1del list1print 'after del list1', sys.getrefcount(11) - 1
輸出:
init 24after a=11 25after b=1 26in func function 28after func(a) 26after list1=[a,12,14] 27after a=12 26after del a 26after del b 25after del list1 24
問(wèn)題:為什么調(diào)用函數(shù)會(huì)令引用計(jì)數(shù)+2
查看一個(gè)對(duì)象的引用計(jì)數(shù)
sys.getrefcount(a)可以查看a對(duì)象的引用計(jì)數(shù),但是比正常計(jì)數(shù)大1,因?yàn)檎{(diào)用函數(shù)的時(shí)候傳入a,這會(huì)讓a的引用計(jì)數(shù)+1
二.循環(huán)引用導(dǎo)致內(nèi)存泄露
def f2(): while True: c1=ClassA() c2=ClassA() c1.t=c2 c2.t=c1 del c1 del c2
執(zhí)行f2(),進(jìn)程占用的內(nèi)存會(huì)不斷增大。
object born,id:0x237cf30object born,id:0x237cf58
新聞熱點(diǎn)
疑難解答
圖片精選
網(wǎng)友關(guān)注