了解列表的内存分配

时间:2015-04-16 11:46:37

标签: python

>>> import sys
>>> sys.getsizeof([])
32
>>> sys.getsizeof([1])
36
>>> sys.getsizeof('')
25
>>> sys.getsizeof('a')
26
>>> sys.getsizeof('cam')
28

我对参考和紧凑阵列有一个模糊的概念。

在Python中,列表是参照数组,因此它们使用更多内存来存储引用元素的内存位置。

我只能从上面的例子中推断出列表中的一个整数占用了额外的4个字节(32 + 4)。 字符串是字符数组。一个unicode字符应该占用2位。

为什么空字符串占用25个字节?

为什么空列表占用32个字节?

3 个答案:

答案 0 :(得分:3)

Read the docs

  

getsizeof()调用对象的__sizeof__方法,添加额外的垃圾收集器开销,如果对象由垃圾收集器管理。

(重点是我的)

答案 1 :(得分:3)

  

我只能从上面的例子中推断出列表中的一个整数占用了额外的4个字节(32 + 4)。

不,你在考虑这个错误。

getsizeof不是递归的。特别是,列表的大小只是列表“header”的大小加上其成员的引用数组。 (在通常的CPython实现中,这些引用是PyObject *指针)列表中的对象类型没有区别,只有多少对象。

(另外,请记住,列表通常在结尾处有松弛。因此,3个元素的列表实际上可能包含4个引用的数组,最后一个是空指针。)

同时,数字1本身可能不会占用任何存储空间。大多数Python实现实习生小整数,因此有一个1对象内置于Python中,无论你为数字1创建了多少个引用,它们都只是对同一个对象的引用;你永远不会创建另外4个字节。

  

为什么空字符串占用25个字节?

字符串与列表类似,字符串“header”,加上一个数组 - 只是一个字符数组,而不是对象的引用。因为它们是不可变的,所以不需要松弛,这使得更容易预测尺寸。如果系统上的空字符串为25个字节,则表示字符串标头为25个字节,因此'abc'将为28个字节,'abcde'为30个字节,依此类推。 (我在这里假设Python 2.x或Python 3.3+;如果你在3.0-3.2,每个字符实际上是2或4个字节。虽然Python 3.3+中的字符串实际上有点复杂;阅读如果你真的想知道,那就是来源。)

  

为什么空列表占用32个字节?

因为这是列表标题的大小。


如果您想查看这些标题中的实际内容,您需要查看实现的来源。假设你正在使用CPython,你可以找到它here。 (这指向最新的主干版本,此时为3.5alpha;您可以使用default2.7或您关注的任何版本替换网址中的3.3。)

例如,列表在C API中的类型为PyListObject。您可以搜索源代码,也可以猜测listobject.h可能是定义PyUnicodeObject的文件。而there,您将看到定义类型的C结构。总结成员,有一个通用标题包含所有类型所需的信息(如refcount),指向实际数组的指针和分配的计数。

答案 2 :(得分:2)

  

unicode字符应占用2位。为什么是一个空字符串   占据25位?

因为Python字符串(字节或unicode)是一个对象,而不是一个unicode字符。

>>> s = "a"
>>> type(s)
<type 'str'>
>>> dir(s)
['__add__', '__class__', '__contains__', '__delattr__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__getslice__', '__gt__', '__hash__', '__init__', '__le__', '__len__', '__lt__', '__mod__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__rmod__', '__rmul__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '_formatter_field_name_split', '_formatter_parser', 'capitalize', 'center', 'count', 'decode', 'encode', 'endswith', 'expandtabs', 'find', 'format', 'index', 'isalnum', 'isalpha', 'isdigit', 'islower', 'isspace', 'istitle', 'isupper', 'join', 'ljust', 'lower', 'lstrip', 'partition', 'replace', 'rfind', 'rindex', 'rjust', 'rpartition', 'rsplit', 'rstrip', 'split', 'splitlines', 'startswith', 'strip', 'swapcase', 'title', 'translate', 'upper', 'zfill']
>>>