如何强制删除一个python对象?

我很好奇python中__del__的细节,什么时候以及为什么它应该被使用,什么不应该被使用。 我已经学会了这样一个艰难的方式,它不是真正的天真地期望从析构函数中得到什么,因为它不是__new__ / __init__的对立面。

 class Foo(object): def __init__(self): self.bar = None def open(self): if self.bar != 'open': print 'opening the bar' self.bar = 'open' def close(self): if self.bar != 'closed': print 'closing the bar' self.bar = 'close' def __del__(self): self.close() if __name__ == '__main__': foo = Foo() foo.open() del foo import gc gc.collect() 

我在文档中看到, 保证__del__()方法在解释器退出时仍然存在的对象被调用。

  1. 如何保证解释器退出时存在的任何Foo实例都closures?
  2. 在上面的代码片断,酒吧closuresdel foogc.collect() …或两者都没有? 如果你想更好地控制这些细节(例如,当对象未被引用时,栏应该被closures),通常的方法是什么?
  3. __del__被调用时,它保证__init__已被调用? 那么如果__init__提升呢?

closures资源的方式是上下文pipe理器,也就是with声明:

 class Foo(object): def __init__(self): self.bar = None def __enter__(self): if self.bar != 'open': print 'opening the bar' self.bar = 'open' return self # this is bound to the `as` part def close(self): if self.bar != 'closed': print 'closing the bar' self.bar = 'close' def __exit__(self, *err): self.close() if __name__ == '__main__': with Foo() as foo: print foo, foo.bar 

输出:

 opening the bar <__main__.Foo object at 0x17079d0> open closing the bar 

2)Python的对象在引用计数为0时被删除。在你的例子中, del foo删除了最后一个引用,所以立即调用__del__ 。 GC没有任何内容。

 class Foo(object): def __del__(self): print "deling", self if __name__ == '__main__': import gc gc.disable() # no gc f = Foo() print "before" del f # f gets deleted right away print "after" 

输出:

 before deling <__main__.Foo object at 0xc49690> after 

gc与删除你的和大多数其他对象无关。 由于自引用或循环引用,在简单引用计数不起作用的时候,可以清理它们:

 class Foo(object): def __init__(self, other=None): # make a circular reference self.link = other if other is not None: other.link = self def __del__(self): print "deling", self if __name__ == '__main__': import gc gc.disable() f = Foo(Foo()) print "before" del f # nothing gets deleted here print "after" gc.collect() print gc.garbage # The GC knows the two Foos are garbage, but won't delete # them because they have a __del__ method print "after gc" # break up the cycle and delete the reference from gc.garbage del gc.garbage[0].link, gc.garbage[:] print "done" 

输出:

 before after [<__main__.Foo object at 0x22ed8d0>, <__main__.Foo object at 0x22ed950>] after gc deling <__main__.Foo object at 0x22ed950> deling <__main__.Foo object at 0x22ed8d0> done 

3)让我们看看:

 class Foo(object): def __init__(self): raise Exception def __del__(self): print "deling", self if __name__ == '__main__': f = Foo() 

得到:

 Traceback (most recent call last): File "asd.py", line 10, in <module> f = Foo() File "asd.py", line 4, in __init__ raise Exception Exception deling <__main__.Foo object at 0xa3a910> 

对象是用__new__创build的,然后以self传递给__init__ 。 在__init__发生exception之后,对象通常没有名称(即f = part不运行),所以它们的引用计数为0.这意味着对象被正常删除,并调用__del__

一般来说,为了确保不pipe发生什么事情,你使用

 from exceptions import NameError try: f = open(x) except ErrorType as e: pass # handle the error finally: try: f.close() except NameError: pass 

finally块将被运行,无论在try块中是否有错误,以及在exceptexcept任何error handling中是否有错误。 如果你没有处理exception,那么在finally块被执行之后,它仍然会被提升。

确保文件closures的一般方法是使用“上下文pipe理器”。

http://docs.python.org/reference/datamodel.html#context-managers

 with open(x) as f: # do stuff 

这会自动closuresf

对于你的问题#2,当引用计数达到零时, bar会立即closures,所以如果没有其他引用, del foo

对象不是由__init__创build的,它们是由__new__创build的。

http://docs.python.org/reference/datamodel.html#object。;

当你做foo = Foo()两件事实际上正在发生,首先是一个新的对象被创build, __new__ ,然后它被初始化, __init__ 。 所以在这两个步骤发生之前,你都不可能打电话给del foo 。 但是,如果__init__有错误, __init__ __del__仍将被调用,因为该对象实际上已经在__new__创build。

编辑:如果引用计数减less到零,则发生删除。

也许你正在寻找一个上下文pipe理器 ?

 >>> class Foo(object): ... def __init__(self): ... self.bar = None ... def __enter__(self): ... if self.bar != 'open': ... print 'opening the bar' ... self.bar = 'open' ... def __exit__(self, type_, value, traceback): ... if self.bar != 'closed': ... print 'closing the bar', type_, value, traceback ... self.bar = 'close' ... >>> >>> with Foo() as f: ... # oh no something crashes the program ... sys.exit(0) ... opening the bar closing the bar <type 'exceptions.SystemExit'> 0 <traceback object at 0xb7720cfc> 
  1. 添加一个closures所有酒吧的退出处理程序 。
  2. 当虚拟机仍在运行时,当对象的引用数量达到0时, __del__()被调用。 这可能是由GC引起的。
  3. 如果__init__()引发一个exception,那么该对象被认为是不完整的, __del__()将不会被调用。