【问题标题】:Class Instance deletion in PythonPython中的类实例删除
【发布时间】:2015-12-17 01:33:10
【问题描述】:

有没有办法让一个类删除它自己的一个实例。我知道你可以为变量做del x,但你如何为类做呢?如果我这样做:

class foo(object):
    x=5
    def __init__(self):
        print "hi"
    def __del__(self):
        del self
        print "bye"

a = foo()
a.__del__()
print a.x

代码的输出是

hi
bye
5

foo 的实例没有被删除。有没有办法让班级这样做?

【问题讨论】:

  • del a 也许?它在这里成功了
  • 郑重声明,x 甚至不是a 的属性,而是foo 的类属性;无论a 引用的foo 实例是否存在,它都不会消失。

标签: python


【解决方案1】:

不,如果您有对该类的实例的引用,那么根据定义,它还有剩余的引用。您可以使用del 关键字来删除名称(释放从该名称到对象的引用),但如果对实例的引用在别处保存,则该实例仍然存在。

如果您要进行确定性清理行为,请不要使用__del__(这不是以明显或一致的方式确定的,并且在 Python 3.4 之前,如果任何成员都可能导致引用循环泄漏cycle 是定义了 __del__ 终结器的类的实例)。让类实现the context manager protocol,并使用带有with 语句的实例来获得确定性清理;在最后一个引用消失之前,实例仍然存在,但只要__exit__ 执行必要的资源释放,实例的空壳几乎不会花费您任何费用。

作为上下文管理的示例,我们将 x 设为 foo 的实例属性,而不是类属性,并且我们会说我们需要确保实例对 x 的引用在已知的情况下消失时间(注意,因为del 只是删除了我们的引用,如果其他人保存了a.x,则该对象实际上不会被释放,直到其他引用也被释放):

class foo(object):
    def __init__(self, x):
        self.x = x
        print "hi"
    def __enter__(self):
        return self
    def __exit__(self, exc_type, exc_val, exc_tb):
        print "bye"
        del self.x

with foo(123456789) as a:
    print a.x  # This works, because a.x still exists
# bye is printed at this point
print a.x # This fails, because we deleted the x attribute in __exit__ and the with is done
# a still exists until it goes out of scope, but it's logically "dead" and empty

【讨论】:

    【解决方案2】:

    通过定义__del__,我相信您会覆盖del 的默认行为。正如您所读到的here,一旦对象的引用计数达到0,就会调用__del__。除非您知道自己在做什么,否则不建议使用__del__

    编辑:这是不正确的,请检查 shadowranger 的答案。尽管该链接仍然与 python 2 相关

    【讨论】:

    • 这是完全错误的。 del 关键字删除一个名称(或在某些情况下,从容器内引用),从而释放对与该名称关联的对象的引用。但是如果其他地方还有其他引用,del 只会(在 CPython 中)减少引用计数。 __del__ 在最后一个引用消失时调用,无论是否涉及 del。两者只是切线相关; del 本身对于带有或不带有 __del__ 的类的实例没有什么不同,只是 Python 垃圾处理过程发生了变化。
    • 好了,我显然还没有完成关于 CPython 垃圾收集的功课。看起来我今天也学到了一些东西,但我相信你有点过头了。我从未说过__del__ 是由del 专门调用的,引用计数为零与没有引用相同,但是我绝对100% 承认我的回答具有误导性,第一句话是错误的。
    【解决方案3】:

    del a 应该可以解决问题:

    代码:

    class foo(object):
        x=5
        def __init__(self):
            print "hi"
        def __del__(self):
            del self
            print "bye"
    
    a = foo()
    del a
    print a.x
    

    输出:

    $ python test.py
    hi
    here
    bye
    Traceback (most recent call last):
      File "test.py", line 12, in <module>
        print a.x
    NameError: name 'a' is not defined
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-05-16
      • 2023-04-03
      • 2015-08-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-01-21
      • 2013-02-23
      相关资源
      最近更新 更多