在Python中,当使用完大对象后,是否应该将它们删除?

11

假设脚本中没有特定的内存优化问题,因此我的问题与Python编码风格有关。这也意味着:在可能的情况下解引用对象是良好和常见的Python实践吗? 情景如下。

类A将一个对象实例化为self.foo并请求第二个类B将其存储和共享给其他对象。 在某个时刻,A决定不再分享self.foo并将其从B中删除。

类A仍然引用foo,但我们知道这个对象从现在开始是无用的。 由于foo是一个相对较大的对象,你会费心去删除A中的引用吗?(例如使用del还是设置self.foo = None这个决定会影响垃圾收集器吗?


3
你有没有研究过弱引用?我认为你的例子非常适合使用它。 - Bort
可能是重复的问题:您更喜欢使用del还是重新分配为None(垃圾回收) - Michael0x2a
@Michael0x2a,感谢您提供的链接,对我的问题有很好的回答。另一半的问题是关于“Pythonic方式”的:在任何可能的情况下都解除对象引用是否是一个好的和常见的做法? - Niccolò
@Niccolò 关于“良好实践”的问题是基于个人意见的,不适合本站的问答格式。 - BartoszKP
@BartoszKP,你有关于如何改进问题的建议吗?我的“良好实践”问题涉及两个方面。首先,正如你所知,Python社区在pythonic和良好代码之间的二分法上非常严格/精确。它对如何处理这种情况有什么建议吗?其次,在这个网站上我看到说“不寻常意味着模糊意味着糟糕的代码”(例如https://dev59.com/12Af5IYBdhLWcg3woz9n#24435904)。如果我每次都像在问题中那样做,会是这样一种情况吗? - Niccolò
@Niccolò 首先,不要在一个问题中询问多个事情。其次,即使Python社区非常严格,可读性特别是“Pythonic”(无论这意味着什么-从我所看到的来看,这个术语似乎被过度使用)的主题并不适合这个网站。请考虑将此类问题发布到Code Review。最后(但并非最不重要的),在垃圾收集环境中,我不会关心这些事情,直到内存分析器指示出特定问题。对于这个问题通常存在一个具体的解决方案,而不是一组主观和模糊的准则。 - BartoszKP
3个回答

7

如果删除属性后,访问该属性并查看是否已设置甚至没有意义,则使用del。如果在删除属性后,程序中的某些部分可能希望检查该空间并查看是否存在任何内容,则使用=None

垃圾收集器无论如何都不会关心。


哦,一个更好的答案(+1),因为你从惯例的角度谈到了差异。 - Joran Beasley

4
del Blah

将减少Blah的引用计数一个,一旦没有更多的引用,Python就会进行垃圾回收。

self.foo = None 

同时也会将Blah的引用计数减一……当没有更多的引用时,Python将对其进行垃圾回收。

这两种方法都不会强制销毁对象……只有一个引用指向它。

* 作为一个经验法则,我建议避免使用 del ,因为它会销毁名称,并且如果在此之后尝试引用它,可能会导致代码中的其他错误……

在cPython(即“正常”的Python)中,垃圾回收非常定期发生。


1
到目前为止,在我使用Python的经验中,我没有遇到任何垃圾回收问题。然而,我会采取预防措施,不仅因为我不想麻烦于任何未引用的对象,也为了组织原因。
具体回答您的问题:
1)是的,我建议删除对象。这将使您的代码不会变得臃肿和/或缓慢。即使Python在垃圾回收方面表现相当出色,如果您的代码运行时间很长,这仍然是一个特别好的决定。
2)无论哪种方法都可以,尽管我会使用del只是为了删除实际的引用本身。
3)我不知道它如何“影响垃圾收集器”,但最好是安全而不是抱歉。

@JoranBeasley:jaysoncopes说得对,如果您不删除引用,对象将会一直存在并占用内存。然而,我不理解他的说法,即这会使程序“变慢”。至于第二点,他说“两种方法都可以正常工作”,这是正确的,但我不明白“为了删除实际引用本身”的意义所在。 - DanielSank
@DanielSank 你说得对...我以为他说的是删除对象时用到的 del ... 另外,高内存消耗肯定会使它变慢...我在真正阅读之前就发表评论了,我的错。+1 点赞来弥补一下,因为基本上是正确的... - Joran Beasley
@JoranBeasley:正如DanielSank所提到的,如果您不删除引用,它将占用内存,毫无疑问。至于声称程序可能运行缓慢,您必须以非常低效的方式使用Python,而删除这些内容将有所帮助。肯定可以使Python程序运行缓慢。最后,将引用设置为“None”并不会删除它,它只是表示它什么也没有。删除引用将删除所有可能的解析方式,提高效率。 - jaysoncopes
1
@JoranBeasley 谢谢。抱歉,我在发布我的解释之前没有看到你的评论 :P - jaysoncopes
@jaysoncopes 请看我上面的回复...同时将ref设置为None,会将som_big_object的引用计数减少1...就像使用del一样...关于#1,我之前说错了,因为我错误地认为当你说“删除对象”时,我把它理解为del - Joran Beasley

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