亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Python萬字深入內(nèi)存管理講解

 更新時(shí)間:2022年07月21日 15:05:22   作者:Flyme?awei  
內(nèi)存管理是指在程序的運(yùn)行過程中,分配內(nèi)容和回收內(nèi)存的過程。如果只分配,不回收,電腦上那點(diǎn)內(nèi)存很快就被用光。幸運(yùn)的是,Python和Java等高級語言會(huì)自動(dòng)管理內(nèi)存的分配和回收

Python內(nèi)存管理

一、對象池

1.小整數(shù)池

系統(tǒng)默認(rèn)創(chuàng)建好的,等著你使用

概述:

整數(shù)在程序中的使用非常廣泛,Python為了優(yōu)化速度,使用了小整數(shù)對象池,避免為整數(shù)頻繁申請和銷毀內(nèi)存空間。

Python 對小整數(shù)的定義是 [-5, 256] ,這些整數(shù)對象是提前建立好的,不會(huì)被垃圾回收。

在一個(gè) Python 的程序中,無論這個(gè)整數(shù)處于LEGB(局部變量,閉包,全局,內(nèi)建模塊)中的哪個(gè)位置,所有位于這個(gè)范圍內(nèi)的整數(shù)使用的都是同一個(gè)對象。

# 交互式環(huán)境下:
>>> a = 100
>>> b = 100
>>> id(a)
140720433537792
>>> id(b)
140720433537792
>>> a is b
True
>>> 

我們可以看出a,b指向同一個(gè)內(nèi)存地址。

2.大整數(shù)池

大整數(shù)池:默認(rèn)創(chuàng)建出來,池內(nèi)為空的,創(chuàng)建一個(gè)就會(huì)往池中存儲(chǔ)一個(gè)

# python交互式環(huán)境
>>> a = 257
>>> b = 257
>>> id(a)
2085029722896
>>> id(b)
2085029722960
>>> a is b
False
>>> 

a , b 不是指向同一個(gè)內(nèi)存地址。

python中對大于256的整數(shù),會(huì)重新分配對象空間地址保存對象。

3.inter機(jī)制(短字符串池)

每個(gè)單詞(字符串),不夾雜空格或者其他符號,默認(rèn)開啟intern機(jī)制,共享內(nèi)存,靠引用計(jì)數(shù)決定是否銷毀。

>>> s1 = 'hello'
>>> s2 = 'hello'
>>> id(s1)
2178093449264
>>> id(s2)
2178093449264
>>> s1 is s2
True
>>> 

字符串s1和s2中沒有空格時(shí),可以看出,這里的s1與s2指向同一個(gè)內(nèi)存地址。

當(dāng)我們在he和llo之間加一個(gè)空格

>>> s1 = 'he llo'
>>> s2 = 'he llo'
>>> id(s1)
2278732636592
>>> id(s2)
2278732636528
>>> s1 is s2
False
>>> 

這時(shí)的字符串s1和s2就沒有指向同一個(gè)內(nèi)存地址。

對于字符串來說,如果不包含空格的字符串,則不會(huì)重新分配對象空間,對于包含空格的字符串則會(huì)重新分配對象空間。

二、垃圾回收

概述:

python采用的是引用計(jì)數(shù)機(jī)制為主,隔代回收和標(biāo)記清除機(jī)制為輔的策略

概述:
現(xiàn)在的高級語言如java,c\# 等,都采用了垃圾收集機(jī)制,而不再是c,c++里用戶自己管理維護(hù)內(nèi)存的方式。

自己管理 內(nèi)存極其自由, 可以任意申請內(nèi)存,但如同一把雙刃劍,為大量內(nèi)存泄露,懸空指針等bug埋下隱患。 

python里也同java一樣采用了垃圾收集機(jī)制,不過不一樣的是: 
python采用的是引用計(jì)數(shù)機(jī)制為主,隔代回收機(jī)制為輔的策略

2.1.引用計(jì)數(shù)

在Python中,每個(gè)對象都有指向該對象的引用總數(shù)---引用計(jì)數(shù) 

查看對象的引用計(jì)數(shù):sys.getrefcount() 

注意:
    當(dāng)使用某個(gè)引用作為參數(shù),傳遞給getrefcount()時(shí),參數(shù)實(shí)際上創(chuàng)建了一個(gè)臨時(shí)的引用。
    因此, getrefcount()所得到的結(jié)果,會(huì)比期望的多1。

2.1.1 引用計(jì)數(shù)增加

a、對象被創(chuàng)建

b、另外變量也指向當(dāng)前對象

c、作為容器對象的一個(gè)元素

d、作為參數(shù)提供給函數(shù):test(x)

2.1.2 引用計(jì)數(shù)減少

a、變量被顯式的銷毀

b、對象的另外一個(gè)變量重新賦值

c、從容器中移除

d、函數(shù)被執(zhí)行完畢

看代碼:

# -*- coding: utf-8 -*-
import sys
class Test(object):
    def __init__(self):
        print('當(dāng)前對象已經(jīng)被創(chuàng)建,占用的內(nèi)存地址為:%s' % hex(id(self)))
a = Test()
print('當(dāng)前對象的引用計(jì)數(shù)為:%s' % sys.getrefcount(a))  # 2
b = a
print('當(dāng)前對象的引用計(jì)數(shù)為:%s' % sys.getrefcount(a))  # 3
list1 = []
list1.append(a)
print('當(dāng)前對象的引用計(jì)數(shù)為:%s' % sys.getrefcount(a))  # 4
del b
print('當(dāng)前對象的引用計(jì)數(shù)為:%s' % sys.getrefcount(a))  # 3
list1.remove(a)
print('當(dāng)前對象的引用計(jì)數(shù)為:%s' % sys.getrefcount(a))  # 2
del a
print('當(dāng)前對象的引用計(jì)數(shù)為:%s' % sys.getrefcount(a))  # 報(bào)錯(cuò)
'''
Traceback (most recent call last):
  File "E:/Python Project/Python 高級編程/內(nèi)存管理/垃圾收集.py", line 30, in <module>
    print('當(dāng)前對象的引用計(jì)數(shù)為:%s' % sys.getrefcount(a))
NameError: name 'a' is not defined
'''

當(dāng)Python的某個(gè)對象的引用計(jì)數(shù)降為0時(shí),說明沒有任何引用指向該對象,該對象就成為要被回收的垃圾。比如某個(gè)新建對象,被分配給某個(gè)引用,對象的引用計(jì)數(shù)變?yōu)?。如 為0,那么該對象就可以被垃圾回收。

2.2.標(biāo)記清除

標(biāo)記清除(Mark—Sweep)算法是一種基于追蹤回收(tracing GC)技術(shù)實(shí)現(xiàn)的垃圾回收算法。

它分為兩個(gè)階段:

第一階段是標(biāo)記階段,GC會(huì)把所有的活動(dòng)對象打上標(biāo)記

第二階段是把那些沒有標(biāo)記的對象非活動(dòng)對象進(jìn)行回收。

對象之間通過引用(指針)連在一起,構(gòu)成一個(gè)有向圖,對象構(gòu)成這個(gè)有向圖的節(jié)點(diǎn),而引用關(guān)系構(gòu)成這個(gè)有向圖的邊。從根對象(root object)出發(fā),沿著有向邊遍歷對象,可達(dá)的(reachable)對象標(biāo)記為活動(dòng)對象,不可達(dá)的對象就是要被清除的非活動(dòng)對象。根對象就是全局變量、調(diào)用棧、寄存器。

>

在上圖中,可以從程序變量直接訪問塊1,并且可以間接訪問塊2和3。程序無法訪問塊4和5。第一步將標(biāo)記塊1,并記住塊2和3以供稍后處理。第二步將標(biāo)記塊2,第三步將標(biāo)記塊3,但不記得塊2,因?yàn)樗驯粯?biāo)記。掃描階段將忽略塊1,2和3,因?yàn)樗鼈円驯粯?biāo)記,但會(huì)回收塊4和5。

標(biāo)記清除算法作為Python的輔助垃圾收集技術(shù),主要處理的是一些容器對象,比如list、dict、tuple等,因?yàn)閷τ谧址?、?shù)值對象是不可能造成循環(huán)引用問題。Python使用一個(gè)雙向鏈表將這些容器對象組織起來。不過,這種簡單粗暴的標(biāo)記清除算法也有明顯的缺點(diǎn):清除非活動(dòng)的對象前它必須順序掃描整個(gè)堆內(nèi)存,哪怕只剩下小部分活動(dòng)對象也要掃描所有對象。

2.3.分代回收

因?yàn)椋?標(biāo)記和清除的過程效率不高。清除非活動(dòng)的對象前它必須順序掃描整個(gè)堆內(nèi)存,哪怕只剩下小部分活動(dòng)對象也要掃描所有對象。還有一個(gè)問題就是:什么時(shí)候掃描去檢測循環(huán)引用?

為了解決上述的問題,python又引入了分代回收。分代回收解決了標(biāo)記清楚時(shí)什么時(shí)候掃描的問題,并且將掃描的對象分成了3級,以及降低掃描的工作量,提高效率。

  • 0代: 0代中對象個(gè)數(shù)達(dá)到700個(gè),掃描一次。
  • 1代: 0代掃描10次,則1代掃描1次。
  • 2代: 1代掃描10次,則2代掃描1次。

隔代回收是用來解決交叉引用(循環(huán)引用),并增加數(shù)據(jù)回收的效率. 原理:通過對象存在的時(shí)間不同,采用不同的算法來 回收垃圾.

形象的比喻, 三個(gè)鏈表,零代鏈表上的對象(新創(chuàng)建的對象都加入到零代鏈表),引用數(shù)都是一,每增加一個(gè)指針,引用加一,隨后 python會(huì)檢測列表中的互相引用的對象,根據(jù)規(guī)則減掉其引用計(jì)數(shù).

GC算法對鏈表一的引用減一,引用為0的,清除,不為0的到鏈表二,鏈表二也執(zhí)行GC算法,鏈表三一樣. 存在時(shí)間越長的 數(shù)據(jù),越是有用的數(shù)據(jù)

2.3.1 分代回收觸發(fā)時(shí)機(jī)?(GC閾值)

隨著你的程序運(yùn)行,Python解釋器保持對新創(chuàng)建的對象,以及因?yàn)橐糜?jì)數(shù)為零而被釋放掉的對象的追蹤。

從理論上說,這兩個(gè)值應(yīng)該保持一致,因?yàn)槌绦蛐陆ǖ拿總€(gè)對象都應(yīng)該最終被釋放掉。當(dāng)然,事實(shí)并非如此。因?yàn)檠h(huán) 引用的原因,從而被分配對象的計(jì)數(shù)值與被釋放對象的計(jì)數(shù)值之間的差異在逐漸增長。一旦這個(gè)差異累計(jì)超過某個(gè)閾 值,則Python的收集機(jī)制就啟動(dòng)了,并且觸發(fā)上邊所說到的零代算法,釋放“浮動(dòng)的垃圾”,并且將剩下的對象移動(dòng)到 一代列表。

隨著時(shí)間的推移,程序所使用的對象逐漸從零代列表移動(dòng)到一代列表。而Python對于一代列表中對象的處理遵循同樣的 方法,一旦被分配計(jì)數(shù)值 與被釋放計(jì)數(shù)值累計(jì)到達(dá)一定閾值,Python會(huì)將剩下的活躍對象移動(dòng)到二代列表。

通過這種方法,你的代碼所長期使用 的對象,那些你的代碼持續(xù)訪問的活躍對象,會(huì)從零代鏈表轉(zhuǎn)移到一代再轉(zhuǎn)移到二代。

通過不同的閾值設(shè)置,Python可 以在不同的時(shí)間間隔處理這些對象。

Python處理零代最為頻繁,其次是一代然后才是二代。

2.3.2 查看引用計(jì)數(shù)(gc模塊的使用)

# 引入gc模塊
import gc 
# 常用函數(shù): 
gc.get_count() 
# 獲取當(dāng)前自動(dòng)執(zhí)行垃圾回收的計(jì)數(shù)器,返回一個(gè)長度為3的列表
gc.get_threshold() 
# 獲取gc模塊中自動(dòng)執(zhí)行垃圾回收的頻率 
gc.set_threshold(threshold0[,threshold1,threshold2]) 
# 設(shè)置自動(dòng)執(zhí)行垃圾回收的頻率 
gc.disable() 
# python3默認(rèn)開啟gc機(jī)制,可以使用該方法手動(dòng)關(guān)閉gc機(jī)制 
gc.collect() 
# 手動(dòng)調(diào)用垃圾回收機(jī)制回收垃圾

內(nèi)存管理是使用計(jì)算機(jī)必不可少的一部分,無論好壞,Python幾乎會(huì)在后臺處理一切內(nèi)存管理的問題。Python抽象出許多使用計(jì)算機(jī)的嚴(yán)格細(xì)節(jié),這讓我們在更高層次進(jìn)行開發(fā),而不用擔(dān)心所有字節(jié)的存儲(chǔ)方式和位置。

# -*- coding: utf-8 -*-
import gc
import sys
import time
class Test(object):
    def __init__(self):
        print('當(dāng)前對象已經(jīng)被創(chuàng)建,占用的內(nèi)存地址為:%s' % hex(id(self)))
    def __del__(self):
        print('當(dāng)前對象馬上被系統(tǒng)GC回收')
# gc.disable()  # 不啟用GC,在python3中默認(rèn)啟用
while True:
    a = Test()
    b = Test()
    a.pro = b  # a 和 b之間相互引用
    b.pro = a
    del a
    del b
    print(gc.get_threshold())  # 打印隔代回收的閾值
    print(gc.get_count())  # 打印GC需要回收的對象
    time.sleep(0.2)  # 休眠0.2秒方便查看

終端輸出:

三、怎么優(yōu)化內(nèi)存管理

1.手動(dòng)垃圾回收

先調(diào)用del a ; 再調(diào)用gc.collect()即可手動(dòng)啟動(dòng)GC

2.調(diào)高垃圾回收閾值

gc.set_threshold 設(shè)置垃圾回收閾值(收集頻率)。

將 threshold 設(shè)為零會(huì)禁用回收。

3.避免循環(huán)引用

四、總結(jié)

python采用的是引用計(jì)數(shù)機(jī)制為主,標(biāo)記-清除和分代回收(隔代回收)兩種機(jī)制為輔的策略

到此這篇關(guān)于Python萬字深入內(nèi)存管理講解的文章就介紹到這了,更多相關(guān)Python內(nèi)存管理內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Python目錄和文件處理總結(jié)詳解

    Python目錄和文件處理總結(jié)詳解

    這篇文章主要介紹了Python目錄和文件處理總結(jié)詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-09-09
  • 用OpenCV進(jìn)行年齡和性別檢測的實(shí)現(xiàn)示例

    用OpenCV進(jìn)行年齡和性別檢測的實(shí)現(xiàn)示例

    這篇文章主要介紹了用 OpenCV 進(jìn)行年齡和性別檢測的實(shí)現(xiàn)示例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-01-01
  • 基于Python制作GIF表情包生成工具

    基于Python制作GIF表情包生成工具

    在當(dāng)前無表情包不會(huì)聊天的時(shí)代,怎么也不能輸在表情包數(shù)量不足上啊,今天咱們就來基于Python制作一個(gè)?gif?生成工具,用來制作表情包也太好用啦
    2023-07-07
  • 詳解TensorFlow查看ckpt中變量的幾種方法

    詳解TensorFlow查看ckpt中變量的幾種方法

    本篇文章主要介紹了詳解TensorFlow查看ckpt中變量的幾種方法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2018-06-06
  • Python列表append()函數(shù)使用方法詳解

    Python列表append()函數(shù)使用方法詳解

    python中的append()函數(shù)是在列表末尾添加新的對象,且將添加的對象最為一個(gè)整體,下面這篇文章主要給大家介紹了關(guān)于Python列表append()函數(shù)使用方法的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-06-06
  • 舉例講解Python常用模塊

    舉例講解Python常用模塊

    今天小編就為大家分享一篇關(guān)于舉例講解Python常用模塊,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧
    2019-03-03
  • OpenCV根據(jù)面積篩選連通域?qū)W習(xí)示例

    OpenCV根據(jù)面積篩選連通域?qū)W習(xí)示例

    這篇文章主要為大家介紹了OpenCV根據(jù)面積篩選連通域?qū)W習(xí)示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-06-06
  • 我在七夕佳節(jié)用Python制作的表白神器,程序員也應(yīng)該擁有愛情!建議收藏

    我在七夕佳節(jié)用Python制作的表白神器,程序員也應(yīng)該擁有愛情!建議收藏

    這篇文章主要介紹了我在七夕佳節(jié)用Python制作的表白神器,建議收藏,程序員也該擁有愛情,感興趣的小伙伴快來看看吧
    2021-08-08
  • 淺析Python?WSGI的使用

    淺析Python?WSGI的使用

    WSGI也稱之為web服務(wù)器通用網(wǎng)關(guān)接口,全稱是web?server?gateway?interface。這篇文章主要為大家介紹了Python?WSGI的使用,希望對大家有所幫助
    2023-04-04
  • Python批量實(shí)現(xiàn)Word/EXCEL/PPT轉(zhuǎn)PDF

    Python批量實(shí)現(xiàn)Word/EXCEL/PPT轉(zhuǎn)PDF

    在日常辦公和文檔處理中,有時(shí)我們需要將多個(gè)Word文檔、Excel表格或PPT演示文稿轉(zhuǎn)換為PDF文件,本文將介紹如何使用Python編程語言批量實(shí)現(xiàn)將多個(gè)Word、Excel和PPT文件轉(zhuǎn)換為PDF文件,需要的可以參考下
    2023-09-09

最新評論