在Python良好实践中定期删除长dicts /列表?

ndi*_*vol 4 python

我一直在写一个很长的脚本,偶尔会构建大的dicts和/或列表,我想知道是否可以通过del在我使用它们时删除它们来改善性能.或者通常的做法是将这些物品留在周围以便通过垃圾收集来处理?这里的最佳做法是什么?谢谢.

Eev*_*vee 7

del不等于免费(3).它不会强制Python释放内存.它可能根本不会释放内存.您应该避免将其与内存使用完全关联.

唯一del能做的就是从其范围中删除一个名称.(或者删除集合中的项目,或删除属性.但我认为这不是你在这里谈论的内容.)

实际上,这个:

del foo
Run Code Online (Sandbox Code Playgroud)

相当于:

del LOCAL_SCOPE['foo']
Run Code Online (Sandbox Code Playgroud)

所以这不会释放任何内存:

massive_list = list(range(1000000))
same_massive_list = massive_list
del massive_list
Run Code Online (Sandbox Code Playgroud)

...因为它所做的就是删除名称 massive_list.底层对象仍有另一个名称same_massive_list,因此它不会消失. del不是用于控制Python内存管理的秘密钩子; 这只是要求 Python 调用其内存管理的几种方法之一.

(顺便说一句,CPython被重新计算+循环收集,而不是垃圾收集.一旦最后一次引用消失,对象立即被释放.垃圾不会等待被清理.当然,其他实现不同事情; PyPy,例如,垃圾收集.)

现在,如果您使用的名称是list/dict/whatever 的唯一名称,那么del肯定会导致其refcount降为零,因此它将被释放. 但是,由于del语义实际上是关于删除名称,我不会在这种情况下使用它.我只是让变量超出范围(如果可行),或者将名称重新分配给空白列表,或者None,或者对您的程序有意义的任何内容.您甚至可以就地清空列表,即使同一列表有多个名称也可以使用:

foo = list(range(1000000))
bar = foo
foo[:] = []
# Both `bar` and `foo` still refer to the original list, but now it's empty
Run Code Online (Sandbox Code Playgroud)

你可以用dict做同样的事情d.clear().

del在名称上使用的唯一地方是在类或模块范围内,我暂时需要一些帮助器值,但实际上我真的不希望将它作为API的一部分公开.这真的很少见,但这是我遇到的唯一一个我真正想要"删除这个名字"的语义的情况.