是什么导致python列表的(大)大小?
当我看到列表和数组时,我感到有点惊讶:是什么导致python列表的(大)大小?,python,list,memory,Python,List,Memory,当我看到列表和数组时,我感到有点惊讶: >>> from sys import getsizeof as sizeof >>> list_ = range(10**6) >>> sizeof(list_) 8000072 与阵列相比: >>> from array import array >>> array_ = array('i', range(10**6)) >>> sizeof(
>>> from sys import getsizeof as sizeof
>>> list_ = range(10**6)
>>> sizeof(list_)
8000072
与阵列相比:
>>> from array import array
>>> array_ = array('i', range(10**6))
>>> sizeof(array_)
56
结果表明,整数列表的大小往往是其所有元素大小的1/3,因此它不能容纳它们:
>>> sizeof(10**8)
24
>>> for i in xrange(0,9):
... round(sizeof(range(10**i)) / ((10**i) * 24.0), 4), "10**%s elements" % (i)
...
(3.3333, '10**0 elements')
(0.6333, '10**1 elements')
(0.3633, '10**2 elements')
(0.3363, '10**3 elements')
(0.3336, '10**4 elements')
(0.3334, '10**5 elements')
(0.3333, '10**6 elements')
(0.3333, '10**7 elements')
(0.3333, '10**8 elements')
是什么导致了这种行为,
list
很大但没有它的所有元素那么大,array
那么小?getsizeof函数不像list那样测量容器中项目的大小。您需要将所有单个元素相加
这是做这件事的秘诀
此处转载:
from __future__ import print_function
from sys import getsizeof, stderr
from itertools import chain
from collections import deque
try:
from reprlib import repr
except ImportError:
pass
def total_size(o, handlers={}, verbose=False):
""" Returns the approximate memory footprint an object and all of its contents.
Automatically finds the contents of the following builtin containers and
their subclasses: tuple, list, deque, dict, set and frozenset.
To search other containers, add handlers to iterate over their contents:
handlers = {SomeContainerClass: iter,
OtherContainerClass: OtherContainerClass.get_elements}
"""
dict_handler = lambda d: chain.from_iterable(d.items())
all_handlers = {tuple: iter,
list: iter,
deque: iter,
dict: dict_handler,
set: iter,
frozenset: iter,
}
all_handlers.update(handlers) # user handlers take precedence
seen = set() # track which object id's have already been seen
default_size = getsizeof(0) # estimate sizeof object without __sizeof__
def sizeof(o):
if id(o) in seen: # do not double count the same object
return 0
seen.add(id(o))
s = getsizeof(o, default_size)
if verbose:
print(s, type(o), repr(o), file=stderr)
for typ, handler in all_handlers.items():
if isinstance(o, typ):
s += sum(map(sizeof, handler(o)))
break
return s
return sizeof(o)
如果您使用该配方并在列表中运行该配方,您可以看到不同之处:
>>> alist=[[2**99]*10, 'a string', {'one':1}]
>>> print('getsizeof: {}, total_size: {}'.format(getsizeof(alist), total_size(alist)))
getsizeof: 96, total_size: 721
您遇到了
array
对象无法正确反映其大小的问题
直到Python2.7.3之前,对象的\uuuSizeOf\uuu()
方法没有准确地反映大小。在Python2.7.4和更新版本上,以及在2012年8月之后发布的任何其他新的Python3版本上,增加了大小
在Python 2.7.5上,我看到:
>>> sys.getsizeof(array_)
4000056L
它符合我的64位系统对基本对象要求的56字节大小,加上包含的每个有符号整数4字节
在Python 2.7.3上,我看到:
>>> sys.getsizeof(array_)
56L
Python
list
我的系统上的对象每个引用使用8个字节,因此它们的大小自然几乎是原来的两倍。首先,列表的sys.getsizeof()
并不度量引用对象占用的内存量。这只是列表
对象本身。这是Python 2还是Python 3?对我来说,在linux2上(在Debian上运行,Linux 3.2.0-4-amd64),数组的内存大小是4000056L
.Python 2.7.3[GCC 4.7.2]。因此,列表只包含对对象的引用,而不包含实际对象的引用。@AshwiniChaudhary:an数组直接包含值(它存储字节数组以提高效率)。在Mac上,内存消耗得到正确反映。在linux上并非如此。但这并不能解释数组
的情况。数组
不是容器。在Mac上,我得到了大小的准确反映,而在Linux上则没有。实际上,对象引用计数和堆链表指针。@MartijnPieters真的吗?我认为这与64位系统上的指针大小有关。@MartijnPieters是的,但是列表的大小只反映了PyObject
指针的大小,所以这些结构包含什么并不重要,是吗?@omz:的确,我搞混了一些东西。列表包含指针,数组包含Cchar
值的数组。大小差异反映了这两种C类型之间的差异,这就足够了。:-)