從三個(gè)方面來(lái)說(shuō):一對(duì)象的引用計(jì)數(shù)機(jī)制,二垃圾回收機(jī)制,三內(nèi)存池機(jī)制。
成都創(chuàng)新互聯(lián)公司是專(zhuān)業(yè)的任城網(wǎng)站建設(shè)公司,任城接單;提供成都做網(wǎng)站、成都網(wǎng)站制作、成都外貿(mào)網(wǎng)站建設(shè),網(wǎng)頁(yè)設(shè)計(jì),網(wǎng)站設(shè)計(jì),建網(wǎng)站,PHP網(wǎng)站建設(shè)等專(zhuān)業(yè)做網(wǎng)站服務(wù);采用PHP框架,可快速的進(jìn)行任城網(wǎng)站開(kāi)發(fā)網(wǎng)頁(yè)制作和功能擴(kuò)展;專(zhuān)業(yè)做搜索引擎喜愛(ài)的網(wǎng)站,專(zhuān)業(yè)的做網(wǎng)站團(tuán)隊(duì),希望更多企業(yè)前來(lái)合作!
一、對(duì)象的引用計(jì)數(shù)機(jī)制
Python內(nèi)部使用引用計(jì)數(shù),來(lái)保持追蹤內(nèi)存中的對(duì)象,所有對(duì)象都有引用計(jì)數(shù)。
引用計(jì)數(shù)增加的情況:
1、一個(gè)對(duì)象分配一個(gè)新名稱(chēng)
2、將其放入一個(gè)容器中(如列表、元組或字典)
sys.getrefcount( )函數(shù)可以獲得對(duì)象的當(dāng)前引用計(jì)數(shù);多數(shù)情況下,引用計(jì)數(shù)比你猜測(cè)得要大得多。對(duì)于不可變數(shù)據(jù)(如數(shù)字和字符串),解釋器會(huì)在程序的不同部分共享內(nèi)存,以便節(jié)約內(nèi)存。
二、垃圾回收機(jī)制
1、當(dāng)一個(gè)對(duì)象的引用計(jì)數(shù)歸零時(shí),它將被垃圾收集機(jī)制處理掉。
2、當(dāng)兩個(gè)對(duì)象a和b相互引用時(shí),del語(yǔ)句可以減少a和b的引用計(jì)數(shù),并銷(xiāo)毀用于引用底層對(duì)象的名稱(chēng)。然而由于每個(gè)對(duì)象都包含一個(gè)對(duì)其他對(duì)象的應(yīng)用,因此引用計(jì)數(shù)不會(huì)歸零,對(duì)象也不會(huì)銷(xiāo)毀。
三、內(nèi)存池機(jī)制
Python提供了對(duì)內(nèi)存的垃圾收集機(jī)制,但是它將不用的內(nèi)存放到內(nèi)存池而不是返回給操作系統(tǒng)。
Pymalloc機(jī)制。為了加速Python的執(zhí)行效率,Python引入了一個(gè)內(nèi)存池機(jī)制,用于管理對(duì)小塊內(nèi)存的申請(qǐng)和釋放。Python中所有小于256個(gè)字節(jié)的對(duì)象都使用pymalloc實(shí)現(xiàn)的分配器,而大的對(duì)象則使用系統(tǒng)的malloc。
擴(kuò)展資料:
Python使用y if cond else x表示條件表達(dá)式。意思是當(dāng)cond為真時(shí),表達(dá)式的值為y,否則表達(dá)式的值為x。相當(dāng)于C++和Java里的cond?y:x。
Python區(qū)分列表(list)和元組(tuple)兩種類(lèi)型。list的寫(xiě)法是[1,2,3],而tuple的寫(xiě)法是(1,2,3)??梢愿淖僱ist中的元素,而不能改變tuple。在某些情況下,tuple的括號(hào)可以省略。tuple對(duì)于賦值語(yǔ)句有特殊的處理。
Python使用'(單引號(hào))和"(雙引號(hào))來(lái)表示字符串。與Perl、Unix Shell語(yǔ)言或者Ruby、Groovy等語(yǔ)言不一樣,兩種符號(hào)作用相同。一般地,如果字符串中出現(xiàn)了雙引號(hào),就使用單引號(hào)來(lái)表示字符串;反之則使用雙引號(hào)。如果都沒(méi)有出現(xiàn),就依個(gè)人喜好選擇。
出現(xiàn)在字符串中的\(反斜杠)被解釋為特殊字符,比如\n表示換行符。表達(dá)式前加r指示Python不解釋字符串中出現(xiàn)的\。這種寫(xiě)法通常用于編寫(xiě)正則表達(dá)式或者Windows文件路徑。
參考資料來(lái)源:百度百科-Python
(1).引用計(jì)數(shù)
(2). 垃圾回收
(3). 內(nèi)存池機(jī)制
在python中每創(chuàng)建一個(gè)對(duì)象,對(duì)應(yīng)的會(huì)有一個(gè)引用計(jì)數(shù),當(dāng)發(fā)生賦值操作如a=b,對(duì)應(yīng)的b的引用計(jì)數(shù)會(huì)自動(dòng)加1,當(dāng)引用的對(duì)象被清除或者函數(shù)結(jié)束時(shí),引用計(jì)數(shù)會(huì)自動(dòng)減1。
在python中使用引用計(jì)數(shù),標(biāo)記清楚,分代回收三種方式進(jìn)行垃圾回收。
其中,引用計(jì)數(shù)當(dāng)對(duì)象的引用計(jì)數(shù)歸0時(shí),對(duì)象會(huì)自動(dòng)被清除。標(biāo)記清除機(jī)制是首先遍歷所有對(duì)象,如果對(duì)象可達(dá),就說(shuō)明有變量引用它,則標(biāo)記其為可達(dá)的。如果不可達(dá),則對(duì)其進(jìn)行清除。分代回收是當(dāng)對(duì)象創(chuàng)建時(shí)被標(biāo)記為第0代,經(jīng)過(guò)一次垃圾回收之后,余下的對(duì)象被標(biāo)記為第1代,最高為第2代。其原理是,對(duì)象的生存期越長(zhǎng),月可能不是垃越。
ython語(yǔ)言雖然提供了對(duì)內(nèi)存的垃圾收集機(jī)制,但實(shí)際上它將不用的內(nèi)存放到內(nèi)存池而不是返回給操作系統(tǒng),所以就有了以下:
1 Pymalloc機(jī)制;這個(gè)主要是為了加速Python的執(zhí)行效率,Python引入了一個(gè)內(nèi)存池機(jī)制,用于管理,為了對(duì)小塊內(nèi)存的申請(qǐng)和釋放。
2 Python中所有小于256個(gè)字節(jié)的對(duì)象都是依靠pymalloc分配器來(lái)實(shí)現(xiàn)的,而稍大的對(duì)象用的則是系統(tǒng)的malloc。
3 對(duì)于Python對(duì)象,比如整數(shù)、浮點(diǎn)數(shù)和List這些,都有自己獨(dú)立的內(nèi)存池,對(duì)象間并不共享他們的內(nèi)存池。換句話說(shuō)就是,假設(shè)你分配并且釋放了大量的整數(shù),那么用于緩存這些整數(shù)的內(nèi)存就不能再分配給浮點(diǎn)數(shù)。
Python的內(nèi)存管理,一般從以下三個(gè)方面來(lái)說(shuō):
1)對(duì)象的引用計(jì)數(shù)機(jī)制(四增五減)
2)垃圾回收機(jī)制(手動(dòng)自動(dòng),分代回收)
3)內(nèi)存池機(jī)制(大m小p)
1)對(duì)象的引用計(jì)數(shù)機(jī)制
要保持追蹤內(nèi)存中的對(duì)象,Python使用了引用計(jì)數(shù)這一簡(jiǎn)單的技術(shù)。sys.getrefcount(a)可以查看a對(duì)象的引用計(jì)數(shù),但是比正常計(jì)數(shù)大1,因?yàn)檎{(diào)用函數(shù)的時(shí)候傳入a,這會(huì)讓a的引用計(jì)數(shù)+1
2)垃圾回收機(jī)制
吃太多,總會(huì)變胖,Python也是這樣。當(dāng)Python中的對(duì)象越來(lái)越多,它們將占據(jù)越來(lái)越大的內(nèi)存。不過(guò)你不用太擔(dān)心Python的體形,它會(huì)在適當(dāng)?shù)臅r(shí)候“減肥”,啟動(dòng)垃圾回收(garbage
collection),將沒(méi)用的對(duì)象清除
從基本原理上,當(dāng)Python的某個(gè)對(duì)象的引用計(jì)數(shù)降為0時(shí),說(shuō)明沒(méi)有任何引用指向該對(duì)象,該對(duì)象就成為要被回收的垃圾了
比如某個(gè)新建對(duì)象,它被分配給某個(gè)引用,對(duì)象的引用計(jì)數(shù)變?yōu)?。如果引用被刪除,對(duì)象的引用計(jì)數(shù)為0,那么該對(duì)象就可以被垃圾回收。
然而,減肥是個(gè)昂貴而費(fèi)力的事情。垃圾回收時(shí),Python不能進(jìn)行其它的任務(wù)。頻繁的垃圾回收將大大降低Python的工作效率。如果內(nèi)存中的對(duì)象不多,就沒(méi)有必要總啟動(dòng)垃圾回收。
所以,Python只會(huì)在特定條件下,自動(dòng)啟動(dòng)垃圾回收。當(dāng)Python運(yùn)行時(shí),會(huì)記錄其中分配對(duì)象(object
allocation)和取消分配對(duì)象(object deallocation)的次數(shù)。當(dāng)兩者的差值高于某個(gè)閾值時(shí),垃圾回收才會(huì)啟動(dòng)。
我們可以通過(guò)gc模塊的get_threshold()方法,查看該閾值。
3)內(nèi)存池機(jī)制
Python中有分為大內(nèi)存和小內(nèi)存:(256K為界限分大小內(nèi)存)
1、大內(nèi)存使用malloc進(jìn)行分配
2、小內(nèi)存使用內(nèi)存池進(jìn)行分配
python中的內(nèi)存管理機(jī)制都有兩套實(shí)現(xiàn),一套是針對(duì)小對(duì)象,就是大小小于256K時(shí),pymalloc會(huì)在內(nèi)存池中申請(qǐng)內(nèi)存空間;當(dāng)大于256K時(shí),則會(huì)直接執(zhí)行系統(tǒng)的malloc的行為來(lái)申請(qǐng)內(nèi)存空間。
由于python中萬(wàn)物皆對(duì)象,所以python的存儲(chǔ)問(wèn)題是對(duì)象的存儲(chǔ)問(wèn)題。實(shí)際上,對(duì)于每個(gè)對(duì)象,python會(huì)分配一塊內(nèi)存空間去存儲(chǔ)它。
那么python是如何進(jìn)行內(nèi)存分配,如何進(jìn)行內(nèi)存管理,又是如何釋放內(nèi)存的呢?
總結(jié)起來(lái)有一下幾個(gè)方面:引用計(jì)數(shù),垃圾回收,內(nèi)存池機(jī)制
python內(nèi)部使用引用計(jì)數(shù),來(lái)保持追蹤內(nèi)存中的對(duì)象,Python內(nèi)部記錄了對(duì)象有多少個(gè)引用,即引用計(jì)數(shù)
1、對(duì)象被創(chuàng)建 a= 'abc'
2、對(duì)象被引用 b =a
3、對(duì)象被其他的對(duì)象引用 li = [1,2,a]
4、對(duì)象被作為參數(shù)傳遞給函數(shù):foo(x)
1、變量被刪除 del a 或者 del b
2、變量引用了其他對(duì)象 b = c 或者 a = c
3、變量離開(kāi)了所在的作用域(函數(shù)調(diào)用結(jié)束) 比如上面的foo(x)函數(shù)結(jié)束時(shí),x指向的對(duì)象引用減1。
4、在其他的引用對(duì)象中被刪除(移除) li.remove(a)
5、窗口對(duì)象本身被銷(xiāo)毀:del li,或者窗口對(duì)象本身離開(kāi)了作用域。
即對(duì)象p中的屬性引用d,而對(duì)象d中屬性同時(shí)來(lái)引用p,從而造成僅僅刪除p和d對(duì)象,也無(wú)法釋放其內(nèi)存空間,因?yàn)樗麄円廊辉诒灰谩I钊虢忉尵褪?,循環(huán)引用后,p和d被引用個(gè)數(shù)為2,刪除p和d對(duì)象后,兩者被引用個(gè)數(shù)變?yōu)?,并不是0,而python只有在檢查到一個(gè)對(duì)象的被引用個(gè)數(shù)為0時(shí),才會(huì)自動(dòng)釋放其內(nèi)存,所以這里無(wú)法釋放p和d的內(nèi)存空間
垃圾回收機(jī)制: ① 引用計(jì)數(shù) , ②標(biāo)記清除 , ③分帶回收
引用計(jì)數(shù)也是一種垃圾收集機(jī)制, 而且也是一種最直觀, 最簡(jiǎn)單的垃圾收集技術(shù).當(dāng)python某個(gè)對(duì)象的引用計(jì)數(shù)降為 0 時(shí), 說(shuō)明沒(méi)有任何引用指向該對(duì)象, 該對(duì)象就成為要被回收的垃圾了.(如果出現(xiàn)循環(huán)引用的話, 引用計(jì)數(shù)機(jī)制就不再起作用了)
優(yōu)點(diǎn):簡(jiǎn)單實(shí)時(shí)性,缺點(diǎn):維護(hù)引用計(jì)數(shù)消耗資源,且無(wú)法解決循環(huán)引用。
如果兩個(gè)對(duì)象的引用計(jì)數(shù)都為 1 , 但是僅僅存在他們之間的循環(huán)引用,那么這兩個(gè)對(duì)象都是需要被回收的, 也就是說(shuō) 它們的引用計(jì)數(shù)雖然表現(xiàn)為非 0 , 但實(shí)際上有效的引用計(jì)數(shù)為 0 ,.所以先將循環(huán)引用摘掉, 就會(huì)得出這兩個(gè)對(duì)象的有效計(jì)數(shù).
標(biāo)記清除算法也有明顯的缺點(diǎn):清除非活動(dòng)的對(duì)象前它必須順序掃描整個(gè)堆內(nèi)存,哪怕只剩下小部分活動(dòng)對(duì)象也要掃描所有對(duì)象。
為了提高效率,有很多對(duì)象,清理了很多次他依然存在,可以認(rèn)為,這樣的對(duì)象不需要經(jīng)?;厥?,可以把它分到不同的集合,每個(gè)集合回收的時(shí)間間隔不同。簡(jiǎn)單的說(shuō)這就是python的分代回收。
具體來(lái)說(shuō),python中的垃圾分為1,2,3代,在1代里的對(duì)象每次回收都會(huì)去清理,當(dāng)清理后有引用的對(duì)象依然存在,此時(shí)他會(huì)進(jìn)入2代集合,同理2代集合清理的時(shí)候存在的對(duì)象會(huì)進(jìn)入3代集合。
每個(gè)集合的清理時(shí)間如何分配:會(huì)先清理1代垃圾,當(dāng)清理10次一代垃圾后會(huì)清理一次2代垃圾,當(dāng)清理10次2代垃圾后會(huì)清理3代垃圾。
在Python中,許多時(shí)候申請(qǐng)的內(nèi)存都是小塊的內(nèi)存,這些小塊內(nèi)存在申請(qǐng)后,很快又會(huì)被釋放,當(dāng)創(chuàng)建大量消耗小內(nèi)存的對(duì)象時(shí),頻繁調(diào)用new/malloc會(huì)導(dǎo)致大量的內(nèi)存碎片,致使效率降低。
內(nèi)存池的概念就是預(yù)先在內(nèi)存中申請(qǐng)一定數(shù)量的,大小相等的內(nèi)存塊留作備用,當(dāng)有新的內(nèi)存需求時(shí),就先從內(nèi)存池中分配內(nèi)存給這個(gè)需求,不夠了之后再申請(qǐng)新的內(nèi)存。這樣做最顯著的優(yōu)勢(shì)就是能夠減少內(nèi)存碎片,提升效率。
Python中有分為大內(nèi)存和小內(nèi)存:(256K為界限分大小內(nèi)存)
大小小于256kb時(shí),pymalloc會(huì)在內(nèi)存池中申請(qǐng)內(nèi)存空間,當(dāng)大于256kb,則會(huì)直接執(zhí)行 new/malloc 的行為來(lái)申請(qǐng)新的內(nèi)存空間
在python中 -5到256之間的數(shù)據(jù),系統(tǒng)會(huì)默認(rèn)給每個(gè)數(shù)字分配一個(gè)內(nèi)存區(qū)域,其后有賦值時(shí)都會(huì)指向固定的已分配的內(nèi)存區(qū)域
在運(yùn)行py程序的時(shí)候,解釋器會(huì)專(zhuān)門(mén)分配一塊空白的內(nèi)存,用來(lái)存放純單詞字符組成的字符串(數(shù)字,字母,下劃線)
字符串賦值時(shí),會(huì)先去查找要賦值的字符串是否已存在于內(nèi)存區(qū)域,已存在,則指向已存在的內(nèi)存,不存在,則會(huì)在大整數(shù)池中分配一塊內(nèi)存存放此字符串