4

Is there a way to have a class delete an instance of itself. I know for variables you can do del x but how do you do that for classes? If I do something like:

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

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

The output of the code is

hi
bye
5

The instance of foo wasn't deleted. Is there a way to make a class do this?

ansg191
  • 419
  • 1
  • 7
  • 16

3 Answers3

2

No, if you have a reference to an instance of the class, then by definition it has remaining references. You can use the del keyword to delete a name (releasing the reference from that name to the object), but if a reference to the instance is held elsewhere, the instance remains.

If what you're going for is deterministic cleanup behavior, don't use __del__ (which is not deterministic in an obvious or consistent way, and prior to Python 3.4, could cause reference cycle leaks if any member of the cycle was an instance of a class that defined a __del__ finalizer). Have the class implement the context manager protocol, and use instances with with statements to get deterministic cleanup; the instance will still exist until the last reference goes away, but as long as __exit__ performs the necessary release of resources, the empty shell of the instance costs you almost nothing.

As an example of context management, we'll make x an instance attribute of foo, not a class attribute, and we'll say we need ensure the instance's reference to x goes away at a known time (note, because del just deletes our reference, if someone else saved off a.x, the object won't actually be freed until the other reference(s) are also released):

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
ShadowRanger
  • 143,180
  • 12
  • 188
  • 271
0

By defining __del__ I believe you're overriding the default behavior of del. As you can read here, __del__ is called once the reference count of an object reaches 0. It is not recommended to use __del__ unless you know what you're doing.

EDIT: this is incorrect, please check shadowranger's answer. Although the link is still relevant to python 2

OnGle
  • 132
  • 6
  • This is flat wrong. `del` the keyword deletes a name (or in some cases, references from within a container) and thereby releases references to the object associated with that name. But if there are other references elsewhere, `del` does nothing but (in CPython) decrement the reference count. `__del__` is invoked when the last reference goes away, regardless of whether `del` was involved or not. The two are only tangentially related; `del` itself does nothing differently for instances of classes with or without `__del__`, only the Python garbage disposal process changes. – ShadowRanger Dec 17 '15 at 01:52
  • Well there you go, I obviously haven't done my homework on CPython garbage collection. Looks like I learned something today too, however I believe you jumped the gun a bit. I never said `__del__` was invoked specifically by `del` and reference count equaling zero is the same as no references however I'll absolutely 100% concede my answer was misleading and the first sentence was wrong. – OnGle Dec 17 '15 at 02:00
-1

del a should do the trick:

Code:

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

a = foo()
del a
print a.x

Output:

$ 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
asiviero
  • 1,225
  • 10
  • 16