覆盖__del __()是最好的选择吗?

时间:2014-02-13 22:08:54

标签: python python-2.7 override del

我试图找出删除内容的最佳方法,最好不必编写大量代码。

在我的项目中,我正在模拟化合物 - 我通过Element实例将Element个实例绑定到其他Bond个实例。在化学债券经常打破,我想有一个干净的方式来做到这一点。我目前的方法如下

# aBond is some Bond instance
#
# all Element instances have a 'bondList' of all bonds they are part of
# they also have a method 'removeBond(someBond)' that removes a given bond 
# from that bondList
element1.removeBond(aBond)
element2.removeBond(aBond)
del aBond

我想做点什么

aBond.breakBond()

class Bond():
    def breakBond(self):
        self.start.removeBond(self) # refers to the first part of the Bond 
        self.end.removeBond(self) # refers to the second part of the Bond 
        del self

或者,像这样的事情会很好

del aBond

class Bond():
    def __del__(self):
        self.start.removeBond(self) # refers to the first part of the Bond 
        self.end.removeBond(self) # refers to the second part of the Bond 
        del self

这些方法中的任何一种方法都优于其他方式,还是有其他方法可以忽略这些方法?

2 个答案:

答案 0 :(得分:5)

Python使用垃圾收集来管理内存,这意味着你必须删除任何东西。这个课很好:

class Bond():
    def breakBond(self):
        self.start.removeBond(self)
        self.end.removeBond(self)

请注意del 从内存中删除任何内容!它只是删除对象的引用,但对象可以有多个引用:

>>> some_list = [1,2,3]
>>> b = some_list
>>> del b   # destroys the list?
>>> b
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'b' is not defined
>>> some_list   # list is still there!
[1, 2, 3]
>>> c = some_list
>>> del some_list
>>> c        # list is still there!
[1, 2, 3]
>>> del c

在最后del c之后,解释器可以解除分配列表。在CPython中,释放将立即完成(在这个简单的情况下),但是在该语言的其他实现中,解释器可能不会立即解除分配列表。

另请注意,__del__的文档引用了这一事实。此外,它是真正的低级方法,您不需要99.9%的时间,所以它当然不是处理您的情况的正确方法。< / p>

答案 1 :(得分:1)

第一种方式非常繁琐且容易出错。第二个很好,但del self中的Bond.breakBond完全没有意义(下面有更多内容)。第三个是hacky,不可靠,并且在这个特定情况下根本不工作(由于Bond和Elements之间的循环引用,除非你升级到Python 3.4,否则永远不会调用__del__,即便如此,它仍然是黑客和不可靠的。)

del name仅删除本地name,不会调用__del__或以其他方式影响对象。它对内存管理完全没有影响,除非name是最后一个(可达)引用,否则可能允许更早的垃圾收集。

你应该这样做:

aBond.breakBond()

class Bond():
    def breakBond(self):
        self.start.removeBond(self) # refers to the first part of the Bond 
        self.end.removeBond(self) # refers to the second part of the Bond