递归删除python字典

2024-09-27 21:31:06 发布

您现在位置:Python中文网/ 问答频道 /正文

我有大量的代码,使用一些自定义类和许多字典。许多类将字典作为属性添加。我发现它占用了太多内存,尤其是当我循环时——即使我手动删除一些类和dict。在

我担心的是,字典被删除了,但是它们所包含的对象仍然存在。为了更好地管理内存,我需要重构代码,但是作为一个快速的解决方案,我希望能够递归地、积极地删除字典。如何实现这一目标?在

这里有一个例子。。。在

def get_lrg():
    return {1: np.zeros((1000,1000,100))}

class H():
    def add_lrg(self):
        fd = get_lrg()
        self.lrg = fd

for cls in ['a', 'b', 'c', 'd']:
    exec('{0} = H()'.format(cls) )
    exec('{0}.add_lrg()'.format(cls) )

del a
del b
del c
del d

另外,在Ipython中玩这个游戏:

^{pr2}$

python的应用程序和应用程序。。。即使在字典“F”被删除之后(例如没有对对象的引用),它似乎也不会“释放”内存。我在我的机器上发现结果是不可预测的。有时内存确实会被刷新,而有时它似乎仍在使用中。在


Tags: 对象内存代码selfadd应用程序formatget
2条回答

如果字典中的对象在你去掉字典之后仍然存在,那么它们应该是活的,因为有些代码引用了它们。在

Python有两种处理内存的方法:

  1. 参考计数
  2. 一种标记式垃圾回收器

删除词典时,您将删除对相关对象的引用。如果这是对这些对象的最后一次引用,它们将自动为您释放。在

但是,如果对象之间存在循环,那么引用计数是不够的,因为这将导致循环中的所有对象至少有一个活动引用,即使不存在外部引用。在

这就是为什么还有一个垃圾回收器来清理这些垃圾,尽管时间稍晚一些。引用计数在引用达到0时处理对象,垃圾回收器稍后开始工作。在

因此,不需要递归地删除任何内容,只需删除对字典的引用,让Python担心其余的事情。在

这里还有另一个问题,以便提供更详细的信息:Why does python use both reference counting and mark-and-sweep for gc?。在

您可以使用以下代码进行验证:

class X:
  def __del__(this):
    print("deleted")

  def __init__(this):
    print("constructed")

print("before")
x = X()
print("after")
del x
print("done")

这将向您展示__del__方法是作为del x语句的一部分执行的。在

然后你有了这个:

^{pr2}$

这将向您展示周期(两个xy相互引用)的处理方式是不同的。在

然后是这样的,我将x存储到字典中,然后删除字典,x对象与字典一起被删除:

class X:
  def __del__(this):
    print("deleted")

  def __init__(this):
    print("constructed")

print("before")
d = {"x": X()}
print("after")
del d
print("done")

当您删除一个对象时,您只是删除了对该对象的引用。如果该对象的引用计数降至0,则从内存中删除该对象对其他对象的引用。在

例如,字典不包含任何对象。它们包含的所有内容都是对其他对象的引用。如果你删除了对字典的所有引用,它会被自动清理、删除,并且它的所有引用也会消失。字典引用的任何键或值的引用计数都将减少1;如果该计数降至0,则这些键或值将被清除。在

因此,不需要递归地删除任何内容。如果对象不再被引用,它们将被自动清理。在

请注意,即使Python释放对象,进程内存的使用情况也不一定是而不是。除非一个进程需要重新分配内存以减少内存的使用量,否则可能需要一个内存重新分配给某个进程。在

相关问题 更多 >

    热门问题