2015-10-23 58 views
6

我很想知道Python中的Bytearray和列表之間的內存管理有何不同。Python中的Bytearray和列表之間的區別

我發現了幾個問題,如Difference between bytearray and list,但不完全回答我的問題。

我的問題正是...

from array import array 
>>> x = array("B", (1,2,3,4)) 
>>> x.__sizeof__() 
36 
>>> y = bytearray((1,2,3,4)) 
>>> y.__sizeof__() 
32 
>>> z = [1,2,3,4] 
>>> z.__sizeof__() 
36 

正如我們可以看到有在列表/ array.array之間的尺寸(36個字節爲4種元素)爲4個元件32個字節的差和一個字節數組( )。有人可以向我解釋這是爲什麼嗎?對於字節數組來說它是有意義的,它佔用32字節的存儲器的4元素(4 * 8 == 32),但是如何解釋list和array.array?

# Lets take the case of bytearray (which makes more sense to me at least :p) 
for i in y: 
     print(i, ": ", id(i)) 

1 : 499962320 
2 : 499962336 #diff is 16 units 
3 : 499962352 #diff is 16 units 
4 : 499962368 #diff is 16 units 

爲什麼兩個連續元素之間的差由16單位這裏不同,當每個元件僅佔據8字節。這是否意味着每個內存地址指針指向一個半字節?

內存分配的整數標準是什麼?我讀到Python會根據整數的值(如果我錯了,糾正我)分配更多的內存,就像內存越大的數字越大。

如:

>>> y = 10 
>>> y.__sizeof__() 
14 
>>> y = 1000000 
>>> y.__sizeof__() 
16 
>>> y = 10000000000000 
>>> y.__sizeof__() 
18 

什麼是Python的分配內存的標準是什麼?

爲什麼Python佔用更多內存,而C只佔用8個字節(我的機器是64位)?當它們完全在整數(2 ** 64)的範圍內時?

元數據:

Python版本:'3.4.3 (v3.4.3:9b73f1c3e601, Feb 24 2015, 22:43:06) [MSC v.1600 32 bit (Intel)]'

機弓: 64位

PS:請指引我的好文章,其中Python的內存管理更好地解釋。我花了將近一個小時的時間來解決這些問題,最終在SO中提出了這個問題。 :(

+2

好問題,upvoted。嘿,你很幸運:在我的Linux Xubuntu 64位機上,CPython 3.4.3'y .__ sizeof __()'給了我''28'給'y = 10','y = 1M','32'爲'y = 10000000000000' – Pynchia

+0

嗨@Pynchia,礦是一個32位的蟒蛇,雖然我的機器是64位。我不確定,但這可能是原因。讓我們等待一些人澄清。 –

回答

1

我不是說這是完整的答案,但也有一些提示,以瞭解這一點。

bytearray是一個字節序列,並list是對象引用的序列。所以[1,2,3]實際持有內存指針到保存在其他地方存儲這些整數。要計算表結構的總內存消耗,我們可以做到這一點(我使用sys.getsizeof到處進一步,它調用__sizeof__加上GC開銷)

>>> x = [1,2,3] 
>>> sum(map(getsizeof, x)) + getsizeof(x) 
172 

結果可能是d如果在不同的機器上。

而且,看看這個:

>> getsizeof([]) 
64 

這是因爲列表是可變的。爲了快速,這個結構分配一些內存範圍來存儲對象的引用(加上一些存儲的元,如列表的長度)。當你添加項目時,下一個存儲單元被填入對這些項目的引用。當沒有空間存儲新的項目時,分配新的更大的範圍,在那裏複製存在的數據和舊的數據。這叫做動態數組。

您可以通過運行此代碼來觀察此行爲。

import sys 
data=[] 
n=15 
for k in range(n): 
    a = len(data) 
    b = sys.getsizeof(data) 
    print('Length: {0:3d}; Size in bytes: {1:4d}'.format(a, b)) 
    data.append(None) 

我的結果:

Length: 0; Size in bytes: 64 
Length: 1; Size in bytes: 96 
Length: 2; Size in bytes: 96 
Length: 3; Size in bytes: 96 
Length: 4; Size in bytes: 96 
Length: 5; Size in bytes: 128 
Length: 6; Size in bytes: 128 
Length: 7; Size in bytes: 128 
Length: 8; Size in bytes: 128 
Length: 9; Size in bytes: 192 
Length: 10; Size in bytes: 192 
Length: 11; Size in bytes: 192 
Length: 12; Size in bytes: 192 
Length: 13; Size in bytes: 192 
Length: 14; Size in bytes: 192 

我們可以看到,有被用來存儲8個存儲器地址(每個64位)64個字節。

幾乎與bytearray()一樣(將第二行更改爲data = bytearray()並在最後一行中追加1)。

Length: 0; Size in bytes: 56 
Length: 1; Size in bytes: 58 
Length: 2; Size in bytes: 61 
Length: 3; Size in bytes: 61 
Length: 4; Size in bytes: 63 
Length: 5; Size in bytes: 63 
Length: 6; Size in bytes: 65 
Length: 7; Size in bytes: 65 
Length: 8; Size in bytes: 68 
Length: 9; Size in bytes: 68 
Length: 10; Size in bytes: 68 
Length: 11; Size in bytes: 74 
Length: 12; Size in bytes: 74 
Length: 13; Size in bytes: 74 
Length: 14; Size in bytes: 74 

不同之處在於內存現在用來保存實際的字節值而不是指針。

希望能幫助你進一步調查。

+0

Hi @ anti1869,感謝您的評論。它非常詳盡和有用。但是我在評論中有以下問題。我無法在此處添加所有信息,因此在下面添加了另一條評論。謝謝 –

+0

根據你的解釋它可以理解爲列表,但是爲什麼字節數組的大小是以56開始的,爲什麼在達到74之後穩定呢?如果你可以給更多的信息,爲什麼64和56初始大小,也會很高興。謝謝 –

+0

檢查出數據結構的源代碼。在那裏你會看到內部容器結構,它在初始化時分配了什麼內存。還有非常清晰的可見增長算法。 https://github.com/python/cpython/blob/master/Objects/listobject.c – anti1869

相關問題