为什么具有相同数据的列表具有不同的大小?
Why do lists with the same data have different sizes?
假设我用两种方式创建 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 内存管理在内部发生了什么?为什么 'same' 列表的大小不同?
当您追加到列表时,由于 性能 原因,内存被过度分配给列表,因此多次追加不需要为列表相应地重新分配内存,这会减慢速度重复追加情况下的整体性能。
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 实现而异(请参阅 list.append
实现 Jython and PyPy)并且不保证存在过度分配。
假设我用两种方式创建 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 内存管理在内部发生了什么?为什么 'same' 列表的大小不同?
当您追加到列表时,由于 性能 原因,内存被过度分配给列表,因此多次追加不需要为列表相应地重新分配内存,这会减慢速度重复追加情况下的整体性能。
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 实现而异(请参阅 list.append
实现 Jython and PyPy)并且不保证存在过度分配。