近期有小伙伴跟我反饋 ,面試有遇到面試官問 python 內存管理機制相關的問題,因為之前沒有特地的去了解過,所以不知道怎么回答。
所以今天就專門寫了這篇 python 內存管理機制的文章,來給大家系統的梳理一下內存管理機制的知識點,以及面試中容易被問到的問題。
通過這篇文章幫你們輕松通關面試中 python 內存管理機制相關的問題。
01、引用計數機制
引用計算機制是咱們 python 中垃圾回收的主要機制,python 解釋器會根據對象的引用計數是否為零,來對進行垃圾回收,釋放內存。接下來我們先來看看什么是引用計數。
如果你想學習自動化測試,我這邊給你推薦一套視頻,這個視頻可以說是B站播放全網第一的接口自動化測試教程,同時在線人數到達1000人,并且還有筆記可以領取及各路大神技術交流:798478386????
【已更新】B站講的最詳細的Python接口自動化測試實戰教程全集(實戰最新版)_嗶哩嗶哩_bilibilihttps://www.bilibili.com/video/BV17p4y1B77x/?spm_id_from=333.337.search-card.all.click
我們先來看一個最簡單的 python 賦值語句
>>> a = 10
這邊給變量 a 賦值了一個數值類型的對象 10, 那么在內存中存儲的時候,a 這個變量指向的是 10 這個對象,此時 10 這個對象的引用計算會加 1。
>>> b=a
當我們再把 a 賦值給變量 b 時,b 引用的也是 a 這個變量引用的值 10,那么這個時候 10 這個對象的引用計數又會加 1。
引用計數增加:
● 對象被創建
● 對象被別的變量引用(賦值給一個變量)
● 對象被作為元素,放在容器中(比如被當作元素放在列表中)
引用計數減少:
●? 對象的別名被顯式的銷毀
●? 對象的一個別名被賦值給其他對象 (例:比如原來的 a=10,被改成 a=100,那么此時 10 的引用計數就減少了)
●? 對象從容器中被移除,或者容器被銷毀(例:對象從列表中被移除,或者列表被銷毀)
●??一個引用離開了它的作用域(調用函數的時候傳進去的參數,在函數運行結束后,該參數的引用即被銷毀)
引用計數查看
咱們如果要查看對象的引用計數,可以通過內置模塊 sys 提供的 getrefcount 方法去查看。
import sys
obj =[11,22,33]
print(sys.getrefcount(obj))
注意點:當使用某個引用作為參數,傳遞給 getrefcount()時,參數實際上創建了一個臨時的引用。因此,getrefcount()所得到的結果,會比期望的多 1 ;對應一些常用的基本數據看到的引用計數值會比較大(因為 python 內部引用)
02、數據池和緩存
1、小整數池
a=1000
a1=1000
b = 10
b1 = 10
# a和a1是否為同一個對象?,b和b1是否為同一個對象?
?問題:a 和 a1 是否為同一個對象?,b 和 b1 是否為同一個對象?
答案:?b 和 b1 是同一個對象,a 和 a1 不是
為什么會出現上述情況呢?
當運行 python 程序時,Python 自動將-5~256 的整數進行了緩存,放在一個‘池’(小整數池)中,無論程序中那些變量指向這些范圍內的整數或者字符串當你將這些整數賦值給變量時,并不會重新創建對象,而是使用已經創建好的緩存對象。
優點:對于一些常用的整數,直接從‘池’里拿來用,避免頻繁的創建和銷毀,提升效率,節約內存
2、intern 機制
intern 機制,也稱為字符串駐留池,是針對于字符串內存管理的一種優化處理的機制。
In [4]: s1='abc'
In [5]: s2 ='abc'
In [6]: s2 is s2
Out[6]: TrueIn [7]: s3='abc?'
In [8]: s4 = 'abc?'
In [9]: s3 is s4
Out[9]: False
#為什么會出現這種情況,同樣是字符串為什么上面兩次賦值,是同一個對象,下面不是。
intern 機制的優點是,在創建新的字符串對象時(如果字符串只包含數字、字母、下劃線),會先在字符串駐留池里面找是否有已經存在的值相同的對象,如果有,則直接拿過來用(引用),避免頻繁的創建和銷毀內存,提升效率。
3、緩存機制
● float、int 、list 等一些內置的數據類型,會緩存 80 個對象
● 元組 會根據元組數據的長度,分別緩存元組長度為 0-20 的對象。
● 其他的自定義類型一般都是緩存 2 個對象
03、垃圾回收機制
● python 的垃圾回收機制用一句話來形容就是:引用計數機制為主,標記-清除和分代收集兩種機制為輔的策略
1、引用計數
● 引用計數:在之前講對象的引用我們講到了,每個對象創建之后都有一個引用計數,當引用計數為 0 的時候,那么此時的的垃圾回收機制會自動把它銷毀,回收內存空間。
● 引用計數存在一個缺點:那就是當兩個對象出現循環引用的時候,那么這個兩個變量始終不會被銷毀,這樣就會導致內存泄漏。
2、標記清除:
首先標記對象(垃圾檢測),然后清除垃圾(垃圾回收),首先初始所有對象標記為白色,并確定根節點對象(這些對象是不會被刪除),標記它們為黑色(表示對象有效),將有效對象引用的對象標記為灰色(表示對象可達,但它們所引用的對象還沒檢查),檢查完灰色對象引用的對象后,將灰色標記為黑色。重復直到不存在灰色節點為止。最后白色結點都是需要清除的對象。
?3、分代回收
分代回收是一種以空間換時間的操作方式,Python 將內存根據對象的存活時間劃分為不同的集合,每個集合稱為一個代,Python 將內存分為了 3“代”,分別為年輕代(第 0 代)、中年代(第 1 代)、老年代(第 2 代),他們對應的是 3 個鏈表,它們的垃圾收集頻率隨著對象存活時間的增大而減小。
?