如果我有一个数字列表,如果我使用字典实现相同的东西,它们是否会占用相同的内存空间?
EG。
list = [[0,1],[1,0]]
dict = {'0,0' = 0 , '0,1' = 1, '1,0' = 1, '1,1' = 0 }
list
和dict
的内存大小是否相同?这将占用更多空间?
答案 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
>>> 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), ...]
在所有条件相同的情况下,选择允许您编写最易读代码的内容。