如何强制Python字典缩小?

时间:2015-07-15 23:23:53

标签: python dictionary memory-management garbage-collection

我在其他语言中经历过这种情况。现在我在Python中遇到了同样的问题。我有一个有很多CRUD动作的字典。可以假设从字典中删除元素应该减少它的内存占用。事实并非如此。一旦字典大小增加(通常加倍),它就永远不会(?)释放分配的内存。我已经进行了这个实验:

import random
import sys
import uuid

a= {}
for i in range(0, 100000):
    a[uuid.uuid4()] = uuid.uuid4()
    if i % 1000 == 0:
        print sys.getsizeof(a)

for i in range(0, 100000):
    e = random.choice(a.keys())
    del a[e]
    if i % 1000 == 0:
        print sys.getsizeof(a)

print len(a)

第一个循环的最后一行是6291736。第二个循环的最后一行也是6291736。字典的大小为0

那么如何解决这个问题呢?有没有办法强制释放内存?

PS:不需要随机做 - 我玩了第二个循环的范围。

2 个答案:

答案 0 :(得分:2)

执行此操作“重新散列”以便使用更少内存的方法是创建新字典并复制内容。

本视频中解释了Python字典的实现:

https://youtu.be/C4Kc8xzcA68

有一位与会者提出同样的问题(https://youtu.be/C4Kc8xzcA68?t=1593),发言者给出的答案是:

  

调整大小仅在插入时计算;当字典缩小它只是获得了很多虚拟条目,当你重新填充它时,它将开始重用它们来存储密钥。 [...]您必须将键和值复制到新词典

答案 1 :(得分:1)

实际上字典可以在调整大小时缩小,但调整大小只发生在不删除键插入时。以下是来自dictresize的{​​{3}}的评论:

  

通过分配新表并重新插入所有表来重组表   物品又来了。删除条目后,新表可能会删除   实际上比旧的小。

顺便说一下,由于另一个答案引用了PyCon 2010字典上的CPython source,并且引用似乎与上述(已存在多年)不一致,我想我会包括完整的引用,缺少部分用粗体。

  

调整大小仅在插入时计算。随着字典的缩小,   它只是获得了很多虚拟条目,当你重新填充它时,它会   只需重新开始使用它们来存储密钥。 直到你才会调整大小   设法以更大的尺寸再次使其三分之二满。所以   删除键时不会调整大小。你必须做一个插入来获得   它要弄清楚它需要缩小。

所以他确实说调整大小操作可以“弄清楚[字典]需要缩小”。但这只发生在插入上。显然,在调整大小期间复制所有键时,可以删除虚拟键,从而减小后备阵列的大小。

然而,目前尚不清楚如何实现这一目标,这就是为什么Rhodes说要将所有内容复制到新词典中。