2017-10-12 108 views
7

說我用兩種方法創建python lists
爲什麼具有相同數據的列表具有不同的大小?

在第一種情況下,我用簡單的賦值:

my_list = [] 
print(my_list, '->', my_list.__sizeof__()) 
my_list = [1] 
print(my_list, '->', my_list.__sizeof__()) 
my_list = [1, 1] 
print(my_list, '->', my_list.__sizeof__()) 

在第二種情況下,我用append()方法的列表:

my_list = [] 
print(my_list, '->', my_list.__sizeof__()) 
my_list.append(1) 
print(my_list, '->', my_list.__sizeof__()) 
my_list.append(1) 
print(my_list, '->', my_list.__sizeof__()) 

但我得到意想不到的(對我來說)輸出:

=== WITH ASSIGNMENT === 
([], '->', 40) 
([1], '->', 48) 
([1, 1], '->', 56) 
=== WITH APPEND === 
([], '->', 40) 
([1], '->', 72) 
([1, 1], '->', 72) 

Python內存管理內部會發生什麼EMENT?爲什麼'相同'的名單有不同的大小?

+2

我猜,因爲當你創建列表作爲一個文字時,Python會指定所需的特定大小,而當你附加到它時,它會擴展超過所需的數值,因爲假設你不會只追加一次。 – jonrsharpe

+0

[內核的Python列表訪問和調整運行時大小](https://stackoverflow.com/questions/5932328/internals-of-python-list-access-and-resizing-runtimes) – anuragal

回答

14

當您附加到列表時,內存會被過度分配到列表性能的原因,因此多個附加內存不需要相應的列表內存重新分配,這會在重複附加的情況下降低總體性能。

的CPython的源清楚地描述此行爲在comment

/* This over-allocates proportional to the list size, making room 
* for additional growth. The over-allocation is mild, but is 
* enough to give linear-time amortized behavior over a long 
* sequence of appends() in the presence of a poorly-performing 
* system realloc(). 
* The growth pattern is: 0, 4, 8, 16, 25, 35, 46, 58, 72, 88, ... 
* Note: new_allocated won't overflow because the largest possible value 
*  is PY_SSIZE_T_MAX * (9/8) + 6 which always fits in a size_t. 
*/ 

在其他情況下,該列表是由文字構成,該列表的大小反映了容器本身和的大小對每個包含對象的引用。

其他Python實現的確切分配行爲可能會有所不同(請參閱JythonPyPylist.append實現),並且不保證存在過度分配。

相關問題