如何强制删除python对象? [英] How to force deletion of a python object?

查看:30
本文介绍了如何强制删除python对象?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我很好奇python中__del__的细节,什么时候以及为什么应该使用它,不应该使用它做什么.我已经艰难地了解到它并不像人们天真地期望从析构函数中得到的那样,因为它不是 __new__/__init__ 的对立面.

I am curious about the details of __del__ in python, when and why it should be used and what it shouldn't be used for. I've learned the hard way that it is not really like what one would naively expected from a destructor, in that it is not the opposite of __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__() 方法在解释器退出时仍然存在的对象被调用.

I saw in the documentation that it is not guaranteed __del__() methods are called for objects that still exist when the interpreter exits.

  1. 如何保证在解释器退出时存在的任何 Foo 实例,栏是关闭的?
  2. 在上面的代码片段中,栏是在 del foo 还是在 gc.collect()... 或两者都不关闭?如果您想更好地控制这些细节(例如,当对象未被引用时应该关闭栏),通常的实现方法是什么?
  3. __del__ 被调用时,是否保证 __init__ 已经被调用了?如果 __init__ 引发了怎么办?
  1. how can it be guaranteed that for any Foo instances existing when the interpreter exits, the bar is closed?
  2. in the code snippet above does the bar get closed on del foo or on gc.collect()... or neither? if you want finer control of those details (e.g. the bar should be closed when the object is unreferenced) what is the usual way to implement that?
  3. when __del__ is called is it guaranteed that __init__ has already been called? what about if the __init__ raised?

推荐答案

关闭资源的方式是上下文管理器,也就是 with 语句:

The way to close resources are context managers, aka the with statement:

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 不参与其中.


2) Python's objects get deleted when their reference count is 0. In your example the del foo removes the last reference so __del__ is called instantly. The GC has no part in this.

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 与删除您和大多数其他对象无关.当简单的引用计数由于自引用或循环引用而不起作用时,它可以进行清理:

The gc has nothing to do with deleting your and most other objects. It's there to clean up when simple reference counting does not work, because of self-references or circular references:

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) 让我们看看:


3) Lets see:

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__ 创建的,然后作为 self 传递给 __init__.在 __init__ 中出现异常后,对象通常没有名称(即 f = 部分未运行),因此它们的引用计数为 0.这意味着正常删除对象并调用__del__.

Objects are created with __new__ then passed to __init__ as self. After a exception in __init__, the object will typically not have a name (ie the f = part isn't run) so their ref count is 0. This means that the object is deleted normally and __del__ is called.

这篇关于如何强制删除python对象?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆