【问题标题】:Deleting attributes when deleting instance删除实例时删除属性
【发布时间】:2010-02-02 00:12:53
【问题描述】:

A 类: def __get(self): 返回self._x

 def __set(self, y):
  self._x = y

 def __delete_x(self):
  print('DELETING')
  del self._x

 x = property(__get,__set,__delete_x)

b = A()

# Here, when b is deleted, i'd like b.x to be deleted, i.e __delete_x()
# called (and for immediate consequence, "DELETING" printed)
del b

【问题讨论】:

    标签: python class attributes instance del


    【解决方案1】:

    del 语句的语义并不真正适合您在这里想要的东西。 del b simple 从本地范围框架/字典中删除对您刚刚实例化的 A 对象的引用;这不会直接导致对对象本身执行任何操作。如果这是对对象的最后一次引用,那么引用计数下降到零,或者垃圾收集器收集一个循环,可能会导致对象被释放。您可以通过向对象添加 __del__ 方法或添加执行所需操作的 weakref 回调来观察这一点。

    不过,后两种解决方案似乎都不是一个好主意; __del__ 方法阻止垃圾收集器收集任何涉及对象的循环;虽然weakrefs 不会遇到这个问题,但在任何一种情况下,您都可能在奇怪的环境中运行(例如在程序关闭期间),这可能会使您难以完成您想要完成的事情。

    如果您可以扩展您的确切用例,可能有一种完全不同的方法可以实现您想要的最终目标,但很难根据这样一个普遍且有限的示例进行推测。

    【讨论】:

    • 没有足够的信息来构成答案,但不要忘记,当您调用 del whatever 时它不会被删除,它只是将 whatever 从它指向的任何地方取消链接,它只是当没有更多对该对象的引用时被删除。
    【解决方案2】:

    要控制A 类的实例消失时发生的情况(无论是被删除还是垃圾回收),您可以在A 中实现特殊方法__del__(self)。如果您希望在该实例的特定 attribute 消失时让您的代码参与进来,您可以使用具有 __del__ 的包装类包装该属性,或者在大多数情况下可能更好,使用weakref 模块(但是,并非所有类型都成为弱引用的目标,因此您可能还需要对这种情况进行一些包装)。

    如果可能的话,通常最好避免使用__del__,因为它会干扰垃圾收集,从而在您有循环引用时导致“内存泄漏”。

    【讨论】:

      【解决方案3】:

      一个丑陋的方法是:

      def __del__(self):
          for x in dir(self.__class__):
              if type(getattr(self.__class__, x)) == property:
                  getattr(self.__class__, x).fdel(self)
      

      【讨论】:

        猜你喜欢
        • 2015-05-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-12-18
        • 1970-01-01
        • 1970-01-01
        • 2016-10-07
        • 2012-10-26
        相关资源
        最近更新 更多