Python:当项被删除时,集合类是否像字典一样“泄漏”?

4

我知道Python的dict在删除项目时会“泄漏”(因为该项目的插槽将被覆盖为神奇的“已删除”值)...但是set类是否会表现出相同的方式?是否安全地保留一个set,并随着时间的推移添加和删除内容?

编辑:好的,我尝试了一下,这是我发现的:

>>> import gc
>>> gc.collect()
0
>>> nums = range(1000000)
>>> gc.collect()
0
### rsize: 20 megs
### 基准测量
>>> s = set(nums)
>>> gc.collect()
0
### rsize: 36 megs
>>> for n in nums: s.remove(n)
>>> gc.collect()
0
### rsize: 36 megs
### 从集合中删除每个项目后,内存使用情况不会降低...
>>> s = None
>>> gc.collect()
0
### rsize: 20 megs
### ...但将对集合的引用设置为NULL *确实*释放了内存。
>>> s = set(nums)
>>> for n in nums: s.remove(n)
>>> for n in nums: s.add(n)
>>> gc.collect()
0
### rsize: 36 megs
### 删除然后重新添加键使用恒定数量的内存...
>>> for n in nums: s.remove(n)
>>> for n in nums: s.add(n+1000000)
>>> gc.collect()
0
### rsize: 47 megs
### ...但添加新键会使用更多内存。

3
当你说 Python 字典会“泄漏”时,你能否具体说明一下?可以提供其他引用来源吗? - Greg Hewgill
2
据我所知,字典实际上不会泄漏 - 有时(例如当您设置新项目时),替换已删除的值的虚拟对象会被清除。 - Eli Bendersky
2个回答

7

是的,set基本上就像dict一样是一个哈希表--接口上的区别并不意味着它们之间有很大的差异。偶尔,你应该复制这个集合--myset = set(myset)--就像你应该为经常进行许多添加和删除操作的字典做的一样。


1
@Anurag,如果你在一个长时间运行的程序中不断添加和删除键,那么dict可能会消耗越来越多的内存并减慢程序速度。 - Alex Martelli
2
称此行为为“泄漏”过于简单化和误导,但重点是对于高频使用的字典或集合,偶尔进行一次全新复制可以节省内存并加快速度! - Alex Martelli

-1

对于这类问题,通常最好运行一个快速实验,就像这个实验一样,看看会发生什么:

s = set()
for a in range(1000):
  for b in range(10000000):
    s.add(b)
  for b in range(10000000):
    s.remove(b)

文档和人们所说的与实际行为往往不一致。如果这对你很重要,那就进行测试。不要依赖他人。


就记录而言,我没有看到那段代码有泄漏的证据。内存使用量一次性上升,然后保持不变。 - JUST MY correct OPINION
通常我会同意……但如果讲述的人是Alex Martelli,我会选择相信他。 - David Wolever
是的,这就是问题所在 - 在所有东西都被清除后,它应该再次下降。而且作为一种GC'd语言,更难以知道何时回收了所有可能被回收的内存。 - David Wolever
@David Wolever - 测试需要根据你要测试的内容进行修改。重点是你需要进行测试,而不是这个特定的测试是要运行的。 ;) - JUST MY correct OPINION

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接