删除实例时删除属性

时间:2010-02-02 00:12:54

标签: python class attributes instance del

A类:      def __get(self):       return 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

3 个答案:

答案 0 :(得分:2)

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

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

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

答案 1 :(得分:1)

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

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

答案 2 :(得分:0)

一种丑陋的方式是:

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