由于python中萬物皆對象,所以python的存儲問題是對象的存儲問題。實際上,對于每個對象,python會分配一塊內(nèi)存空間去存儲它。
創(chuàng)新互聯(lián)堅持“要么做到,要么別承諾”的工作理念,服務領域包括:網(wǎng)站建設、成都網(wǎng)站設計、企業(yè)官網(wǎng)、英文網(wǎng)站、手機端網(wǎng)站、網(wǎng)站推廣等服務,滿足客戶于互聯(lián)網(wǎng)時代的耿馬網(wǎng)站設計、移動媒體設計的需求,幫助企業(yè)找到有效的互聯(lián)網(wǎng)解決方案。努力成為您成熟可靠的網(wǎng)絡建設合作伙伴!
那么python是如何進行內(nèi)存分配,如何進行內(nèi)存管理,又是如何釋放內(nèi)存的呢?
總結(jié)起來有一下幾個方面:引用計數(shù),垃圾回收,內(nèi)存池機制
python內(nèi)部使用引用計數(shù),來保持追蹤內(nèi)存中的對象,Python內(nèi)部記錄了對象有多少個引用,即引用計數(shù)
1、對象被創(chuàng)建 a= 'abc'
2、對象被引用 b =a
3、對象被其他的對象引用 li = [1,2,a]
4、對象被作為參數(shù)傳遞給函數(shù):foo(x)
1、變量被刪除 del a 或者 del b
2、變量引用了其他對象 b = c 或者 a = c
3、變量離開了所在的作用域(函數(shù)調(diào)用結(jié)束) 比如上面的foo(x)函數(shù)結(jié)束時,x指向的對象引用減1。
4、在其他的引用對象中被刪除(移除) li.remove(a)
5、窗口對象本身被銷毀:del li,或者窗口對象本身離開了作用域。
即對象p中的屬性引用d,而對象d中屬性同時來引用p,從而造成僅僅刪除p和d對象,也無法釋放其內(nèi)存空間,因為他們依然在被引用。深入解釋就是,循環(huán)引用后,p和d被引用個數(shù)為2,刪除p和d對象后,兩者被引用個數(shù)變?yōu)?,并不是0,而python只有在檢查到一個對象的被引用個數(shù)為0時,才會自動釋放其內(nèi)存,所以這里無法釋放p和d的內(nèi)存空間
垃圾回收機制: ① 引用計數(shù) , ②標記清除 , ③分帶回收
引用計數(shù)也是一種垃圾收集機制, 而且也是一種最直觀, 最簡單的垃圾收集技術(shù).當python某個對象的引用計數(shù)降為 0 時, 說明沒有任何引用指向該對象, 該對象就成為要被回收的垃圾了.(如果出現(xiàn)循環(huán)引用的話, 引用計數(shù)機制就不再起作用了)
優(yōu)點:簡單實時性,缺點:維護引用計數(shù)消耗資源,且無法解決循環(huán)引用。
如果兩個對象的引用計數(shù)都為 1 , 但是僅僅存在他們之間的循環(huán)引用,那么這兩個對象都是需要被回收的, 也就是說 它們的引用計數(shù)雖然表現(xiàn)為非 0 , 但實際上有效的引用計數(shù)為 0 ,.所以先將循環(huán)引用摘掉, 就會得出這兩個對象的有效計數(shù).
標記清除算法也有明顯的缺點:清除非活動的對象前它必須順序掃描整個堆內(nèi)存,哪怕只剩下小部分活動對象也要掃描所有對象。
為了提高效率,有很多對象,清理了很多次他依然存在,可以認為,這樣的對象不需要經(jīng)?;厥?,可以把它分到不同的集合,每個集合回收的時間間隔不同。簡單的說這就是python的分代回收。
具體來說,python中的垃圾分為1,2,3代,在1代里的對象每次回收都會去清理,當清理后有引用的對象依然存在,此時他會進入2代集合,同理2代集合清理的時候存在的對象會進入3代集合。
每個集合的清理時間如何分配:會先清理1代垃圾,當清理10次一代垃圾后會清理一次2代垃圾,當清理10次2代垃圾后會清理3代垃圾。
在Python中,許多時候申請的內(nèi)存都是小塊的內(nèi)存,這些小塊內(nèi)存在申請后,很快又會被釋放,當創(chuàng)建大量消耗小內(nèi)存的對象時,頻繁調(diào)用new/malloc會導致大量的內(nèi)存碎片,致使效率降低。
內(nèi)存池的概念就是預先在內(nèi)存中申請一定數(shù)量的,大小相等的內(nèi)存塊留作備用,當有新的內(nèi)存需求時,就先從內(nèi)存池中分配內(nèi)存給這個需求,不夠了之后再申請新的內(nèi)存。這樣做最顯著的優(yōu)勢就是能夠減少內(nèi)存碎片,提升效率。
Python中有分為大內(nèi)存和小內(nèi)存:(256K為界限分大小內(nèi)存)
大小小于256kb時,pymalloc會在內(nèi)存池中申請內(nèi)存空間,當大于256kb,則會直接執(zhí)行 new/malloc 的行為來申請新的內(nèi)存空間
在python中 -5到256之間的數(shù)據(jù),系統(tǒng)會默認給每個數(shù)字分配一個內(nèi)存區(qū)域,其后有賦值時都會指向固定的已分配的內(nèi)存區(qū)域
在運行py程序的時候,解釋器會專門分配一塊空白的內(nèi)存,用來存放純單詞字符組成的字符串(數(shù)字,字母,下劃線)
字符串賦值時,會先去查找要賦值的字符串是否已存在于內(nèi)存區(qū)域,已存在,則指向已存在的內(nèi)存,不存在,則會在大整數(shù)池中分配一塊內(nèi)存存放此字符串
python的內(nèi)存駐留機制,是一種節(jié)省內(nèi)存的方案,它將int, str, bool類型的數(shù)據(jù)做成小數(shù)據(jù)池。當程序要創(chuàng)建字符串等對象前會先檢查池中是否有滿足的字符串。
駐留機制節(jié)省大量的重復內(nèi)存。在內(nèi)部,小數(shù)據(jù)池是由一個全局的dict 維護,該字典中的對象成了單例模式,從而節(jié)省內(nèi)存。
變量 interned 就是全局存放字符串池的字典的變量名 interned = PyDict_New() ,為了讓 intern 機制中的字符串不被回收,設置字典時 PyDict_SetDefault(interned, s, s); 將字符串作為鍵同時也作為值進行設置,這樣對于字符串對象的引用計數(shù)就會進行兩次 +1 操作,這樣存于字典中的對象在程序結(jié)束前永遠不會為 0,這也是 y_REFCNT(s) -= 2; 將計數(shù)減 2 的原因。
從函數(shù)參數(shù)中可以看到其實字符串對象還是被創(chuàng)建了,內(nèi)部其實始終會為字符串創(chuàng)建對象,但經(jīng)過 inter 機制檢查后,臨時創(chuàng)建的字符串會因引用計數(shù)為 0 而被銷毀,臨時變量在內(nèi)存中曇花一現(xiàn)然后迅速消失。
指定要駐留的字符串:
為什么要進行字符串駐留呢?
總結(jié):
系統(tǒng)維護一個interned全局字典,記錄已被駐留的字符串對象,當新字符串a(chǎn)對象需要駐留時,先在interned中查找是否存在,若存在則指向已存在的字符串對象,a對象的引用計數(shù)減1,若不存在,則記錄a對象到interned中。
分區(qū)表錯誤是硬盤的嚴重錯誤,不同錯誤的程度會造成不同的損失。如果是沒有活動分區(qū)標志,則計算機無法啟動。但從軟區(qū)或光區(qū)引導系統(tǒng)后可對硬盤讀寫,可通過fdisk重置活動分區(qū)進行修復。如果是某一分區(qū)類型錯誤,可造成某一分區(qū)的丟失。分區(qū)表的第四個字節(jié)為分區(qū)類型值,正常的可引導的大于32mb的基本DOS分區(qū)值為06,而擴展的DOS分區(qū)值是05。如果把基本DOS分區(qū)類型改為05則無法啟動系統(tǒng) ,并且不能讀寫其中的數(shù)據(jù)。如果把06改為DOS不識別的類型如efh,則DOS認為改分區(qū)不是 DOS分區(qū),當然無法讀寫。很多人利用此類型值實現(xiàn)單個分區(qū)的加密技術(shù),恢復原來的正確類型值即可使該分區(qū)恢復正常。分區(qū)表中還有其他數(shù)據(jù)用于紀錄分區(qū)的起始或終止地址。這些數(shù)據(jù)的損壞將造成該分區(qū)的混亂或丟失,一般無法進行手工恢復,唯一的方法是用備份的分區(qū)表數(shù)據(jù)重新寫回,或者從其他的相同類型的并且分區(qū)狀況相同的硬盤上獲取分區(qū)表數(shù)據(jù),否則將導致其他的數(shù)據(jù)永久的丟失。在對主引導扇區(qū)進行操作時,可采用nu等工具軟件,操作非常的方便,可直接對硬盤主引導扇區(qū)進行讀寫或編輯。當然也可采用de
在python中可以用id()函數(shù)獲取對象的內(nèi)存地址。
#例如:
object = 1 + 2
print(id(object)) #4304947776
Python的內(nèi)存管理主要有三種機制:引用計數(shù)機制,垃圾回收機制和內(nèi)存池機制。
引用計數(shù)機制
簡介
python內(nèi)部使用引用計數(shù),來保持追蹤內(nèi)存中的對象,Python內(nèi)部記錄了對象有多少個引用,即引用計數(shù),當對象被創(chuàng)建時就創(chuàng)建了一個引用計數(shù),當對象不再需要時,這個對象的引用計數(shù)為0時,它被垃圾回收。
特性
1.當給一個對象分配一個新名稱或者將一個對象放入一個容器(列表、元組或字典)時,該對象的引用計數(shù)都會增加。
2.當使用del對對象顯示銷毀或者引用超出作用于或者被重新賦值時,該對象的引用計數(shù)就會減少。
3.可以使用sys.getrefcount()函數(shù)來獲取對象的當前引用計數(shù)。多數(shù)情況下,引用計數(shù)要比我們猜測的大的多。對于不可變數(shù)據(jù)(數(shù)字和字符串),解釋器會在程序的不同部分共享內(nèi)存,以便節(jié)約內(nèi)存。
垃圾回收機制
特性
1.當內(nèi)存中有不再使用的部分時,垃圾收集器就會把他們清理掉。它會去檢查那些引用計數(shù)為0的對象,然后清除其在內(nèi)存的空間。當然除了引用計數(shù)為0的會被清除,還有一種情況也會被垃圾收集器清掉:當兩個對象相互引用時,他們本身其他的引用已經(jīng)為0了。
2.垃圾回收機制還有一個循環(huán)垃圾回收器, 確保釋放循環(huán)引用對象(a引用b, b引用a, 導致其引用計數(shù)永遠不為0)。
內(nèi)存池機制
簡介
在Python中,許多時候申請的內(nèi)存都是小塊的內(nèi)存,這些小塊內(nèi)存在申請后,很快又會被釋放,由于這些內(nèi)存的申請并不是為了創(chuàng)建對象,所以并沒有對象一級的內(nèi)存池機制。這就意味著Python在運行期間會大量地執(zhí)行malloc和free的操作,頻繁地在用戶態(tài)和核心態(tài)之間進行切換,這將嚴重影響Python的執(zhí)行效率。為了加速Python的執(zhí)行效率,Python引入了一個內(nèi)存池機制,用于管理對小塊內(nèi)存的申請和釋放。
內(nèi)存池概念
內(nèi)存池的概念就是預先在內(nèi)存中申請一定數(shù)量的,大小相等的內(nèi)存塊留作備用,當有新的內(nèi)存需求時,就先從內(nèi)存池中分配內(nèi)存給這個需求,不夠了之后再申請新的內(nèi)存。這樣做最顯著的優(yōu)勢就是能夠減少內(nèi)存碎片,提升效率。內(nèi)存池的實現(xiàn)方式有很多,性能和適用范圍也不一樣。
特性
1.Python提供了對內(nèi)存的垃圾收集機制,但是它將不用的內(nèi)存放到內(nèi)存池而不是返回給操作系統(tǒng)。
2.Pymalloc機制。為了加速Python的執(zhí)行效率,Python引入了一個內(nèi)存池機制,用于管理對小塊內(nèi)存的申請和釋放。
3.Python中所有小于256個字節(jié)的對象都使用pymalloc實現(xiàn)的分配器,而大的對象則使用系統(tǒng)的 malloc。
4.對于Python對象,如整數(shù),浮點數(shù)和List,都有其獨立的私有內(nèi)存池,對象間不共享他們的內(nèi)存池。也就是說如果你分配又釋放了大量的整數(shù),用于緩存這些整數(shù)的內(nèi)存就不能再分配給浮點數(shù)。
(1).引用計數(shù)
(2). 垃圾回收
(3). 內(nèi)存池機制
在python中每創(chuàng)建一個對象,對應的會有一個引用計數(shù),當發(fā)生賦值操作如a=b,對應的b的引用計數(shù)會自動加1,當引用的對象被清除或者函數(shù)結(jié)束時,引用計數(shù)會自動減1。
在python中使用引用計數(shù),標記清楚,分代回收三種方式進行垃圾回收。
其中,引用計數(shù)當對象的引用計數(shù)歸0時,對象會自動被清除。標記清除機制是首先遍歷所有對象,如果對象可達,就說明有變量引用它,則標記其為可達的。如果不可達,則對其進行清除。分代回收是當對象創(chuàng)建時被標記為第0代,經(jīng)過一次垃圾回收之后,余下的對象被標記為第1代,最高為第2代。其原理是,對象的生存期越長,月可能不是垃越。
ython語言雖然提供了對內(nèi)存的垃圾收集機制,但實際上它將不用的內(nèi)存放到內(nèi)存池而不是返回給操作系統(tǒng),所以就有了以下:
1 Pymalloc機制;這個主要是為了加速Python的執(zhí)行效率,Python引入了一個內(nèi)存池機制,用于管理,為了對小塊內(nèi)存的申請和釋放。
2 Python中所有小于256個字節(jié)的對象都是依靠pymalloc分配器來實現(xiàn)的,而稍大的對象用的則是系統(tǒng)的malloc。
3 對于Python對象,比如整數(shù)、浮點數(shù)和List這些,都有自己獨立的內(nèi)存池,對象間并不共享他們的內(nèi)存池。換句話說就是,假設你分配并且釋放了大量的整數(shù),那么用于緩存這些整數(shù)的內(nèi)存就不能再分配給浮點數(shù)。
當前名稱:python函數(shù)內(nèi)存,Python操作內(nèi)存
路徑分享:http://jinyejixie.com/article4/hopoie.html
成都網(wǎng)站建設公司_創(chuàng)新互聯(lián),為您提供用戶體驗、電子商務、ChatGPT、服務器托管、定制網(wǎng)站、外貿(mào)建站
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)