Python内存大小

Python内存大小,python,memory,memory-management,Python,Memory,Memory Management,如果我有一个数字列表,如果我使用字典实现相同的事情,它们会占用相同的内存空间吗 例如 list和dict的内存大小是否相同?哪个会占用更多的空间?字典很有可能会更大 字典和列表都是完全不同的数据结构。当它归结为内存和处理器指令时,列表相当简单:列表中的所有值都是连续的,当您想访问项n时,可以从列表的开头开始,向前移动n项,然后返回它。这很容易,因为列表项是连续的,并且具有整数键 另一方面,字典的约束条件则大不相同。您不能只转到字典的开头,向前移动key项并返回它,因为key可能不是数字。此外,键

如果我有一个数字列表,如果我使用字典实现相同的事情,它们会占用相同的内存空间吗

例如


list
dict
的内存大小是否相同?哪个会占用更多的空间?

字典很有可能会更大

字典和列表都是完全不同的数据结构。当它归结为内存和处理器指令时,列表相当简单:列表中的所有值都是连续的,当您想访问项
n
时,可以从列表的开头开始,向前移动
n
项,然后返回它。这很容易,因为列表项是连续的,并且具有整数键

另一方面,字典的约束条件则大不相同。您不能只转到字典的开头,向前移动
key
项并返回它,因为
key
可能不是数字。此外,键不需要是连续的

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


巧合的是,两者的尺寸可能相同,尽管这有点令人惊讶。尽管如此,无论怎样,数据表示形式都会有所不同。

字典很可能会更大

字典和列表都是完全不同的数据结构。当它归结为内存和处理器指令时,列表相当简单:列表中的所有值都是连续的,当您想访问项
n
时,可以从列表的开头开始,向前移动
n
项,然后返回它。这很容易,因为列表项是连续的,并且具有整数键

另一方面,字典的约束条件则大不相同。您不能只转到字典的开头,向前移动
key
项并返回它,因为
key
可能不是数字。此外,键不需要是连续的

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


巧合的是,两者的尺寸可能相同,尽管这有点令人惊讶。尽管如此,无论发生什么情况,数据表示形式都会有所不同。

如果您使用的是Python 2.6或更高版本,您可以使用

>>> 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
占用了更多的内存空间。

如果您使用的是Python 2.6或更高版本,则可以使用来进行测试

>>> 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
占用了更多的内存空间。

在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

在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

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

正如其他几个人所提到的,getsizeof不会对包含的对象求和

这里有一个配方,可以为您在标准python(3.0)类型上做一些工作

在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
从逻辑上看,最好的内存选项是使用两个列表:

list_x = [0, 1, ...]
list_y = [1, 0, ...]
只有当你的内存很紧,而且你的列表预计会很大的时候,这才是值得的。我猜那不是真的