如何强制删除python对象?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (219)

我很好奇__del__在python中,应该在什么时候、为什么要使用它,以及它不应该用于什么。

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实例,当解释器退出时,条形条是否关闭?
  2. 在上面的代码片段中,条形图是否关闭?del foo或对gc.collect()...或者两者都不需要?如果你想更好地控制这些细节(例如,当对象未被引用时,应该关闭条形条),那么实现这些细节的通常方法是什么?
  3. 何时__del__是被调用的,它保证__init__已经被调用了?
提问于
用户回答回答于

关闭资源的方式是上下文管理器,也就是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__然后传递给__init__as self。在发生异常之后__init__,对象通常没有名称(即该f =部分未运行),因此它们的引用计数为0.这意味着对象被正常删除并被__del__调用。

用户回答回答于

一般来说,为了确保无论发生什么事情都可以使用

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块中是否存在错误处理错误,都将运行except块。如果你没有处理引发的异常,那么在finally块被执行后它仍然会被提升。

确保文件关闭的一般方法是使用“上下文管理器”。

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

with open(x) as f:
    # do stuff

这将自动关闭f

对于问题#2,bar当引用计数达到零时立即关闭,del foo如果没有其他引用,则立即关闭。

对象不是由__init__它们创建的,而是由它们创建的__new__

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

当你做foo = Foo()两件事实际上发生时,首先创建一个新的对象__new__,然后它正在被初始化,__init__。因此,del foo在这两个步骤发生之前,你无法调用。但是,如果出现错误__init____del__仍然会被调用,因为该对象实际上已经被创建__new__

扫码关注云+社区

领取腾讯云代金券