Python内存大小

时间:2010-12-31 06:40:18

标签: python memory memory-management

如果我有一个数字列表,如果我使用字典实现相同的东西,它们是否会占用相同的内存空间?

EG。

list = [[0,1],[1,0]]
dict = {'0,0' = 0 , '0,1' = 1, '1,0' = 1, '1,1' = 0 }

listdict的内存大小是否相同?这将占用更多空间?

4 个答案:

答案 0 :(得分:3)

如果您使用的是Python 2.6或更高版本,则可以使用sys.getsizeof()进行测试

>>> import sys
>>> aList = [[0,1],[1,0]]
>>> aDict = {'0,0' : 0 , '0,1' : 1, '1,0' : 1, '1,1' : 0 }
>>> sys.getsizeof(aList)
44
>>> sys.getsizeof(aDict)
140

通过您提供的示例,我们发现aDict占用了更多的内存空间。

答案 1 :(得分:1)

字典很可能会更大。

字典和列表都是完全不同的数据结构。当它归结为内存和处理器指令时,列表相当简单:其中的所有值都是连续的,当您想要访问项n时,您将转到列表的开头,移动{{1}物品前进,并返回它。这很简单,因为列表项是连续的并且具有整数键。

另一方面,词典的限制是完全不同的。您不能只是转到字典的开头,向前移动n项并将其返回,因为key可能不是数字。此外,密钥不需要是连续的。

对于字典,您需要一种结构来非常容易地找到与键关联的值,即使它们之间可能没有关系。因此,它不能使用列表使用的同类算法。通常,字典所需的数据结构比列表所需的数据结构要大。

巧合的是,两者的大小可能相同,即使它有点令人惊讶。但是,数据表示不同,无论如何。

答案 2 :(得分:1)

在python中获取对象的大小很棘手。表面上看,这可以通过sys.getsizeof来完成,但它会返回不完整的数据。

我的系统上空列表的大小使用量为32个字节。

>>> sys.getsizeof([])
32

包含一个元素的列表的大小为36个字节。这似乎不会因元素而异。

>>> sys.getsizeof([[1, 2]])
36
>>> sys.getsizeof([1])
36

所以你需要知道内部列表的大小。

>>> sys.getsizeof([1, 2])
40

因此,列表的内存使用情况(假设与我的系统相同)应为32字节加上每个内部列表的44字节。这是因为python存储了保持列表成本为32字节所涉及的开销。每个添加条目都表示为指向该对象的指针,成本为4个字节。因此,指针在您存储的任何内容上花费4个字节。在两个元素列表的情况下,这是40个字节。

对于dict,空的dict

为136
>>> sys.getsizeof({})
136

从那里开始,它的大小将增加四倍,因为添加成员会导致空间不足并导致频繁的哈希冲突。同样,您必须包括要存储的对象的大小和键。

>>> sys.getsizeof({1: 2})
136

答案 3 :(得分:1)

简而言之,它们将不一样。该列表应该表现更好,除非您可以在dict中实现稀疏填充的列表。

正如其他几个人所提到的,getsizeof并没有对包含的对象求和。

这是一个在标准python(3.0)类型上为你工作的配方。

Compute Memory footprint of an object and its contents

在python 3.1上使用这个配方是一些结果:

aList = [[x,x] for x in range(1000)]
aListMod10 = [[x%10,x%10] for x in range(1000)]
aTuple = [(x,x) for x in range(1000)]
aDictString = dict(("%s,%s" % (x,x),x) for x in range(1000))
aDictTuple = dict(((x,x),x) for x in range(1000))

print("0", total_size(0))
print("10", total_size(10))
print("100", total_size(100))
print("1000", total_size(1000))

print("[0,1]", total_size([0,1]))
print("(0,1)", total_size((0,1)))

print("aList", total_size(aList))
print("aTuple", total_size(aTuple))
print("aListMod10", total_size(aListMod10))
print("aDictString", total_size(aDictString))
print("aDictTuple", total_size(aDictTuple))

print("[0]'s", total_size([0 for x in range(1000)]))
print("[x%10]'s", total_size([x%10 for x in range(1000)]))
print("[x%100]'s", total_size([x%100 for x in range(1000)]))
print("[x]'s", total_size([x for x in range(1000)]))

输出:

0 12
10 14
100 14
1000 14

[0,1] 70
(0,1) 62

aList 62514
aTuple 54514
aListMod10 48654
aDictString 82274
aDictTuple 74714

[0]'s 4528
[x%10]'s 4654
[x%100]'s 5914
[x]'s 18514

从逻辑上讲,最好的内存选项似乎是使用2个列表:

list_x = [0, 1, ...]
list_y = [1, 0, ...]

如果您的内存不足并且您的列表预计很大,这可能是值得的。我猜这个使用模式无论如何都会在整个地方创建(x,y)元组,所以可能你应该真的这样做:

tuples = [(0, 1), (1, 0), ...]

在所有条件相同的情况下,选择允许您编写最易读代码的内容。