2017-10-12 105 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实现),并且不保证存在过度分配。

相关问题