python基于值得内存_为什么说Python采用的是基于值的内存管理模式
匿名用戶
1級(jí)
2018-01-31 回答
先從較淺的層面來說,Python的內(nèi)存管理機(jī)制可以從三個(gè)方面來講
(1)垃圾回收
(2)引用計(jì)數(shù)
(3)內(nèi)存池機(jī)制
一、垃圾回收:
python不像C++,Java等語言一樣,他們可以不用事先聲明變量類型而直接對(duì)變量進(jìn)行賦值。對(duì)Python語言來講,對(duì)象的類型和內(nèi)存都是
在運(yùn)行時(shí)確定的。這也是為什么我們稱Python語言為動(dòng)態(tài)類型的原因(這里我們把動(dòng)態(tài)類型可以簡單的歸結(jié)為對(duì)變量內(nèi)存地址的分配是在運(yùn)行時(shí)自動(dòng)判斷變量
類型并對(duì)變量進(jìn)行賦值)。
二、引用計(jì)數(shù):
Python采用了類似Windows內(nèi)核對(duì)象一樣的方式來對(duì)內(nèi)存進(jìn)行管理。每一個(gè)對(duì)象,都維護(hù)這一個(gè)對(duì)指向該對(duì)對(duì)象的引用的計(jì)數(shù)。如圖所示(圖片來自Python核心編程)
x = 3.14
y = x
我們首先創(chuàng)建了一個(gè)對(duì)象3.14, 然后將這個(gè)浮點(diǎn)數(shù)對(duì)象的引用賦值給x,因?yàn)閤是第一個(gè)引用,因此,這個(gè)浮點(diǎn)數(shù)對(duì)象的引用計(jì)數(shù)為1. 語句y =
x創(chuàng)建了一個(gè)指向同一個(gè)對(duì)象的引用別名y,我們發(fā)現(xiàn),并沒有為Y創(chuàng)建一個(gè)新的對(duì)象,而是將Y也指向了x指向的浮點(diǎn)數(shù)對(duì)象,使其引用計(jì)數(shù)為2.
我們可以很容易就證明上述的觀點(diǎn):
變量a 和 變量b的id一致(我們可以將id值想象為C中變量的指針).
我們?cè)硪粋€(gè)網(wǎng)址的圖片來說明問題:對(duì)于C語言來講,我們創(chuàng)建一個(gè)變量A時(shí)就會(huì)為為該變量申請(qǐng)一個(gè)內(nèi)存空間,并將變量值
放入該空間中,當(dāng)將該變量賦給另一變量B時(shí)會(huì)為B申請(qǐng)一個(gè)新的內(nèi)存空間,并將變量值放入到B的內(nèi)存空間中,這也是為什么A和B的指針不一致的原因。如圖:
而Python的情況卻不一樣,實(shí)際上,Python的處理方式和Javascript有點(diǎn)類似,如圖所示,變量更像是附在對(duì)象上的標(biāo)簽(和引用的
定義類似)。當(dāng)變量被綁定在一個(gè)對(duì)象上的時(shí)候,該變量的引用計(jì)數(shù)就是1,(還有另外一些情況也會(huì)導(dǎo)致變量引用計(jì)數(shù)的增加),系統(tǒng)會(huì)自動(dòng)維護(hù)這些標(biāo)簽,并定
時(shí)掃描,當(dāng)某標(biāo)簽的引用計(jì)數(shù)變?yōu)?的時(shí)候,該對(duì)就會(huì)被回收。
三、內(nèi)存池機(jī)制
Python的內(nèi)存機(jī)制以金字塔行,-1,-2層主要有操作系統(tǒng)進(jìn)行操作,
第0層是C中的malloc,free等內(nèi)存分配和釋放函數(shù)進(jìn)行操作;
第1層和第2層是內(nèi)存池,有Python的接口函數(shù)PyMem_Malloc函數(shù)實(shí)現(xiàn),當(dāng)對(duì)象小于256K時(shí)有該層直接分配內(nèi)存;
第3層是最上層,也就是我們對(duì)Python對(duì)象的直接操作;
在 C 中如果頻繁的調(diào)用 malloc 與 free 時(shí),是會(huì)產(chǎn)生性能問題的.再加上頻繁的分配與釋放小塊的內(nèi)存會(huì)產(chǎn)生內(nèi)存碎片. Python 在這里主要干的工作有:
如果請(qǐng)求分配的內(nèi)存在1~256字節(jié)之間就使用自己的內(nèi)存管理系統(tǒng),否則直接使用 malloc.
這里還是會(huì)調(diào)用 malloc 分配內(nèi)存,但每次會(huì)分配一塊大小為256k的大塊內(nèi)存.
經(jīng)由內(nèi)存池登記的內(nèi)存到最后還是會(huì)回收到內(nèi)存池,并不會(huì)調(diào)用 C 的 free
釋放掉.以便下次使用.對(duì)于簡單的Python對(duì)象,例如數(shù)值、字符串,元組(tuple不允許被更改)采用的是復(fù)制的方式(深拷貝?),也就是說當(dāng)將另
一個(gè)變量B賦值給變量A時(shí),雖然A和B的內(nèi)存空間仍然相同,但當(dāng)A的值發(fā)生變化時(shí),會(huì)重新給A分配空間,A和B的地址變得不再相同;
而對(duì)于像字典(dict),列表(List)等,改變一個(gè)就會(huì)引起另一個(gè)的改變,也稱之為淺拷貝:
附錄:
引用計(jì)數(shù)增加
1.對(duì)象被創(chuàng)建:x=4
2.另外的別人被創(chuàng)建:y=x
3.被作為參數(shù)傳遞給函數(shù):foo(x)
4.作為容器對(duì)象的一個(gè)元素:a=[1,x,’33’]
引用計(jì)數(shù)減少
1.一個(gè)本地引用離開了它的作用域。比如上面的foo(x)函數(shù)結(jié)束時(shí),x指向的對(duì)象引用減1。
2.對(duì)象的別名被顯式的銷毀:del x ;或者del y
3.對(duì)象的一個(gè)別名被賦值給其他對(duì)象:x=789
4.對(duì)象從一個(gè)窗口對(duì)象中移除:myList.remove(x)
5.窗口對(duì)象本身被銷毀:del myList,或者窗口對(duì)象本身離開了作用域。
垃圾回收
1、當(dāng)內(nèi)存中有不再使用的部分時(shí),垃圾收集器就會(huì)把他們清理掉。它會(huì)去檢查那些引用計(jì)數(shù)為0的對(duì)象,然后清除其在內(nèi)存的空間。當(dāng)然除了引用計(jì)數(shù)為0的會(huì)被清除,還有一種情況也會(huì)被垃圾收集器清掉:當(dāng)兩個(gè)對(duì)象相互引用時(shí),他們本身其他的引用已經(jīng)為0了。
2、垃圾回收機(jī)制還有一個(gè)循環(huán)垃圾回收器, 確保釋放循環(huán)引用對(duì)象(a引用b, b引用a, 導(dǎo)致其引用計(jì)數(shù)永遠(yuǎn)不為0)。
總結(jié)
以上是生活随笔為你收集整理的python基于值得内存_为什么说Python采用的是基于值的内存管理模式的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: python gui框架_Python的
- 下一篇: 歇后语蚂蚁搬家的下一句是什么啊?
