很多人學(xué)習(xí)python峭咒,不知道從何學(xué)起。
很多人學(xué)習(xí)python纪岁,掌握了基本語(yǔ)法過(guò)后凑队,不知道在哪里尋找案例上手。
很多已經(jīng)做案例的人幔翰,卻不知道如何去學(xué)習(xí)更加高深的知識(shí)漩氨。
那么針對(duì)這三類(lèi)人西壮,我給大家提供一個(gè)好的學(xué)習(xí)平臺(tái),免費(fèi)領(lǐng)取視頻教程叫惊,電子書(shū)籍款青,以及課程的源代碼!??¤
QQ群:1057034340
深入Python中引用計(jì)數(shù)
在python中的垃圾回收機(jī)制主要是以引用計(jì)數(shù)為主要手段以標(biāo)記清除和隔代回收機(jī)制為輔的手段 赋访。可以對(duì)內(nèi)存中無(wú)效數(shù)據(jù)的自動(dòng)管理缓待!在這篇文章蚓耽,帶著這個(gè)問(wèn)題來(lái)一直往下看:怎么知道一個(gè)對(duì)象能不能被調(diào)用了呢?
在python中的垃圾回收機(jī)制主要是以引用計(jì)數(shù)為主要手段以標(biāo)記清除和隔代回收機(jī)制為輔的手段 旋炒〔接疲可以對(duì)內(nèi)存中無(wú)效數(shù)據(jù)的自動(dòng)管理!在這篇文章,帶著這個(gè)問(wèn)題來(lái)一直往下看:怎么知道一個(gè)對(duì)象能不能被調(diào)用了呢?
回顧內(nèi)存地址
Python中的任何變量都有對(duì)應(yīng)的內(nèi)存引用瘫镇,也就是內(nèi)存地址鼎兽。
如果不是容器類(lèi)型,那么直接引用和賦值铣除,內(nèi)存地址都是不會(huì)的谚咬。
如果在內(nèi)存中創(chuàng)建了一個(gè)list對(duì)象(容器),而且對(duì)該對(duì)象進(jìn)行了引用尚粘。那么b = [1,2]和c = a有什么區(qū)別择卦?
首先在內(nèi)存1966828025736處創(chuàng)建了一個(gè)列表 [1,2],然后定義了一個(gè)名為a的變量郎嫁。b = [1,2]會(huì)新開(kāi)一個(gè)內(nèi)存地址秉继,c = a直接賦值直接引用[1,2]的內(nèi)存地址。
引用計(jì)數(shù)
在一些代碼中泽铛,如果存在一些變量但是沒(méi)有用尚辑,會(huì)造成內(nèi)存空間,因此叫做垃圾盔腔,所以要回收杠茬。
引用計(jì)數(shù)也是一種最直觀,最簡(jiǎn)單的垃圾收集技術(shù)弛随。原理非常簡(jiǎn)單澈蝙,每一個(gè)對(duì)象都包含了兩個(gè)頭部信息,一個(gè)是類(lèi)型標(biāo)志符撵幽,標(biāo)識(shí)這個(gè)對(duì)象的類(lèi)型;另一個(gè)是計(jì)數(shù)器灯荧,記錄當(dāng)前指向該對(duì)象的引用數(shù)目,表示這個(gè)對(duì)象被多少個(gè)變量名所引用盐杂。
CPython 使用引用計(jì)數(shù)來(lái)管理內(nèi)存逗载,所有 Python 腳本中創(chuàng)建的實(shí)例哆窿,都會(huì)有一個(gè)引用計(jì)數(shù),來(lái)記錄有多少個(gè)指針指向它厉斟。當(dāng)引用計(jì)數(shù)只有 0 時(shí)挚躯,則會(huì)自動(dòng)釋放內(nèi)存。
在Python中通過(guò)sys.getrefcount查看引用計(jì)數(shù)的方法擦秽,
注意調(diào)用getrefcount()函數(shù)會(huì)臨時(shí)增加一次引用計(jì)數(shù)码荔,得到的結(jié)果比預(yù)期的多一次。
比如感挥,下面這個(gè)例子中缩搅,a 的引用計(jì)數(shù)是 3,因?yàn)橛?a触幼、b 和作為參數(shù)傳遞的 getrefcount 這三個(gè)地方硼瓣,都引用了一個(gè)空列表。
我們通過(guò)一些例子來(lái)看下置谦,可以使python對(duì)象的引用計(jì)數(shù)增加或減少的場(chǎng)景堂鲤。
引用計(jì)數(shù)是用來(lái)記錄對(duì)象被引用的次數(shù),每當(dāng)對(duì)象被創(chuàng)建或者被引用時(shí)將該對(duì)象的引用次數(shù)加一媒峡,當(dāng)對(duì)象的引用被銷(xiāo)毀時(shí)該對(duì)象的引用次數(shù)減一瘟栖,當(dāng)對(duì)象的引用次數(shù)減到零時(shí)說(shuō)明程序中已經(jīng)沒(méi)有任何對(duì)象持有該對(duì)象的引用,換言之就是在以后的程序運(yùn)行中不會(huì)再次使用到該對(duì)象了谅阿,那么其所占用的空間也就可以被釋放了了慢宗。
計(jì)數(shù)增加和減少
下面引用計(jì)數(shù)增加的場(chǎng)景:
對(duì)象被創(chuàng)建并賦值給某個(gè)變量,比如:a = 'ABC'
變量間的相互引用(相當(dāng)于變量指向了同一個(gè)對(duì)象)奔穿,比如:b=a
變量作為參數(shù)傳到函數(shù)中镜沽。比如:ref_method(a),
將對(duì)象放到某個(gè)容器對(duì)象中(列表贱田、元組缅茉、字典)。比如:c = [1, a, 'abc']
引用計(jì)數(shù)減少的場(chǎng)景:
當(dāng)一個(gè)變量離開(kāi)了作用域男摧,比如:函數(shù)執(zhí)行完成時(shí)蔬墩,執(zhí)行方法前后的引用計(jì)數(shù)保持不變,這就是因?yàn)榉椒▓?zhí)行完后耗拓,對(duì)象的引用計(jì)數(shù)也會(huì)減少拇颅,如果在方法內(nèi)打印,則能看到引用計(jì)數(shù)增加的效果乔询。
對(duì)象的引用變量被銷(xiāo)毀時(shí)樟插,比如del a或者del b。注意如果del a,再去獲取a的引用計(jì)數(shù)會(huì)直接報(bào)錯(cuò)黄锤。
對(duì)象被從容器對(duì)象中移除搪缨,比如:c.remove(a)
直接將整個(gè)容器銷(xiāo)毀,比如:del c
對(duì)象的引用被賦值給其他對(duì)象鸵熟,相當(dāng)于變量不指向之前的對(duì)象副编,而是指向了一個(gè)新的對(duì)象,這種情況流强,引用計(jì)數(shù)肯定會(huì)發(fā)生改變痹届。(排除兩個(gè)對(duì)象默認(rèn)引用計(jì)一致的場(chǎng)景)。