5

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?

3
  • del a maybe? It did the trick here Commented Dec 17, 2015 at 1:36
  • stackoverflow.com/questions/16686788/… Commented Dec 17, 2015 at 1:52
  • For the record, x isn't even an attribute of a, it's a class attribute of foo; it's not going to go away whether or not the foo instance referenced by a exists or not. Commented Dec 17, 2015 at 1:54

3 Answers 3

3

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
Sign up to request clarification or add additional context in comments.

Comments

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

2 Comments

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.
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.
-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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.