views:

73

answers:

4

Hello,

class 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

Thanks.

+1  A: 

To control what happens when an instance of class A goes away (whether by being deleted or garbage collected), you can implement special method __del__(self) in A. If you want to have your code involved when a specific attribute of that instance goes away, you can either wrap that attribute with a wrapper class which has __del__, or, probably better in most cases, use the weakref module (however, not all types are subject to being target of weak references, so you may also need some wrapping for this case).

Avoiding __del__ is generally preferable, if you possibly can, because it can interfere with garbage collection and thereby cause "memory leaks" if and when you have circular references.

Alex Martelli
+2  A: 

The semantics of the del statement don't really lend themselves to what you want here. del b simple removes the reference to the A object you just instantiated from the local scope frame / dictionary; this does not directly cause any operation to be performed on the object itself. If that was the last reference to the object, then the reference count dropping to zero, or the garbage collector collecting a cycle, may cause the object to be deallocated. You could observe this by adding a __del__ method to the object, or by adding a weakref callback that performs the desired actions.

Neither of the latter two solutions seems like a great idea, though; __del__ methods prevent the garbage collector from collecting any cycles involving the object; and while weakrefs do not suffer from this problem, in either case you may be running in a strange environment (such as during program shutdown), which may make it difficult to get done what you want to accomplish.

If you can expand on your exact use case, it may be that there is an entirely different approach to accomplishing your desired end goal, but it is difficult to speculate based on such a general and limited example.

mithrandi
Not really enough info to constitute an answer, but don't forget that it doesn't get deleted when you call `del whatever`, that just unlinks `whatever` from whatever it pointed to, it only gets deleted when there are no more references to the object.
Richo
A: 

In fact, it goes more like that :

class C(dict):
    def link(self, name):
        _get = lambda x   : A().get(name)
        _set = lambda x, y: A().set(name, y)
        _del = lambda x   : A().delete(name)

        if name not in self:
            self[name] = ''

        return property(_get, _set, _del)

    def delete(self, name):
        print('-- deleting', name, '--')
        del self[name]

    def set(self, variable, value):
        self[variable] = value

_instance = C()

# Singleton
def A():
    return _instance

class B:
    x = A().link('x')

ins_b = B()

# i'd like A().delete('x') to be called
del ins_b

My idea is to build a dictionary referencing every var, in order to display them, store them in, or load them from a file for example.

fc
A: 

An ugly way to do it would be :

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