今天我在 Python 2.7.13 中运行了下面给出的代码,发现当它为空时列表大小不为0:
import sys as s
data = []
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 : 72
Length: 1; Size in bytes : 104
Length: 2; Size in bytes : 104
Length: 3; Size in bytes : 104
Length: 4; Size in bytes : 104
Length: 5; Size in bytes : 136
Length: 6; Size in bytes : 136
Length: 7; Size in bytes : 136
Length: 8; Size in bytes : 136
Length: 9; Size in bytes : 200
Length: 10; Size in bytes : 200
Length: 11; Size in bytes : 200
Length: 12; Size in bytes : 200
Length: 13; Size in bytes : 200
Length: 14; Size in bytes : 200
Length: 15; Size in bytes : 200
Length: 16; Size in bytes : 200
Length: 17; Size in bytes : 272
Length: 18; Size in bytes : 272
Length: 19; Size in bytes : 272
我想知道为什么会这样?
似乎Python正在为某些东西保留内存。 那是什么东西?
答案 0 :(得分:4)
因为从sys.getsizeof
返回的列表大小不仅包含列表包含的元素。
Python中的每个对象都由C
- struct表示;这个结构包含指向使列表成为列表的所有事物的指针(主要是它的方法)。调用sys.getsizeof
时也会考虑到这一点。
您可以随时查看GitHub上CPython存储库主分支中的ProcessCmdKey
:
static PyObject *
list___sizeof___impl(PyListObject *self)
{
Py_ssize_t res;
res = _PyObject_SIZE(Py_TYPE(self)) + self->allocated * sizeof(void*);
return PyLong_FromSsize_t(res);
}
(修剪不相关的arg诊所输出。)
sizeof
implementation of list.__sizeof__
做同样的事情。
返回值res
还包括列表对象类型_PyObject_SIZE(Py_Type(self))
的大小。
由于Python中的所有内容都是对象,因此可以在任何地方观察到此行为,e.x,整数0
:
>>> getsizeof(0)
24
虽然你通常不会期望这一点,但当你意识到Python中的所有东西都有“额外的包袱”允许我们认为理所当然的行为时,它就非常有意义。
答案 1 :(得分:1)
Python在C中实现,因此将数据存储在C结构中。
请记住,所有事物都是'对象' - 对象必须具有类型和对象大小,即使他们不存储任何。
以下是PyObject_VAR_HEAD
和PyListObject
C数据类型。
#define PyObject_VAR_HEAD \
PyObject_HEAD \
Py_ssize_t ob_size; /* Number of items in variable part */
typedef struct {
PyObject_VAR_HEAD
/* Vector of pointers to list elements. list[0] is ob_item[0], etc. */
PyObject **ob_item;
/* ob_item contains space for 'allocated' elements. The number
* currently in use is ob_size.
* Invariants:
* 0 <= ob_size <= allocated
* len(list) == ob_size
* ob_item == NULL implies ob_size == allocated == 0
* list.sort() temporarily sets allocated to -1 to detect mutations.
*
* Items must normally not be NULL, except during construction when
* the list is not yet visible outside the function that builds it.
*/
Py_ssize_t allocated;
} PyListObject;
请记住,sys.getsizeof()
将返回基础内存使用情况,而不是您真正需要考虑或担心Python的内容:
以字节为单位返回对象的大小。
只考虑直接归因于对象的内存消耗,而不是它所引用的对象的内存消耗。
此外,正如您的测试所示,有一定数量的预分配正在进行中。新内存与每次 list
的上的append()
无关。