Python內存分配小祕密,一般人我不告訴他

Python內存分配小秘密,一般人我不告訴他

Python裡面如何查看對象所佔用的內存?這裡我們需要使用到Python內置的sys模塊,sys模塊負責程序與Python解釋器的交互,提供了一系列的函數和變量,用於控制Python的運行時環境。

查看對象佔用內存字節大小使用到sys模塊的getsizeof()方法。

Python內存分配小秘密,一般人我不告訴他

從上面代碼中可以看出:

1.getsizeof方法可計算對象所佔用內存字節數

2.getsizeof方法只計算對象直接佔用的內存,而不計算對象內所引用對象的內存

看到這裡可能有人疑惑,為什麼同樣的一個列表我這裡申請的內存跟上圖不一樣?

其實這裡跟Python解釋器有關,32位的解釋器創建對象時申請的內存空間要小於64位。

空對象並不“空”

在Python裡面有個None表示什麼都不是,大家是否好奇過這個None到底是什麼?其實None也是一個對象,其類型為NoneType。我們所熟知空對象還有空字符串,空列表,空字典,空元組。當程序創建一個空對象時,這個空對象是否佔用內存呢?

Python內存分配小秘密,一般人我不告訴他

雖然都是空對象,但是這些對象在內存分配上並不為“空”。

天啊!空對象居然佔用內存,為什麼會這樣呢?

除了None對象外,其他空對象都是容器,可以理解為創建這個容器本身就需要佔用一定的內存,還有一部分內存是對象在初始化的時候預分配。這就是我們看到的空對象也佔用這麼大內存原因。

空對象並不為空,一部分原因是 Python 解釋器為它們預分配了一些初始空間。在不超出初始內存的情況下,每次新增元素,就使用已有內存,因而避免了再去申請新的內存。

內存擴容

創建對象的時候只會分配少量的內存空間,在以後追加元素的對象佔用內存必須擴容。那麼是如何擴容?每次擴容多大?

下面我們來看下list,set,dict 三個對象的擴容過程

Python內存分配小秘密,一般人我不告訴他

Python內存分配小秘密,一般人我不告訴他

Python內存分配小秘密,一般人我不告訴他

分別給三類可變對象添加 30個元素,看看結果如何:

Python內存分配小秘密,一般人我不告訴他

從結果上我們可以看出來:

1.每次申請內存都是比實際需要內存要多,這種超額申請,主要是為了避免頻繁申請內存,導致不必要的開銷。

2.每次申請內存不是均勻申請,而是逐漸變大。

刪除元素不會釋放內存

新增元素的時候會申請新內存,那麼刪除元素是否新申請的內存是否會釋放?

看下面的代碼對比:

Python內存分配小秘密,一般人我不告訴他

列表在一擴一縮後,雖然列表的元素回到原樣,但是所佔用的內存空間可沒有自動釋放啊。字典,集合等等可變對象同理。

空字典不等於空字典

pop方法是刪除一個元素,並不會釋放新申請的內存,clear方法是清空所有元素。

下面來看clear方法清空之後內存是否會釋放。

先回憶下文章開篇講的創建空對象講的每個對象申請的內存,如下圖:

Python內存分配小秘密,一般人我不告訴他

調用clear方法後,獲得三個空對象,計算每個對象佔用的內存。


分享到:


相關文章: