Python Object Deleting Itself

Python class instances deleting themselves

Now, why would you do that?

Objects in Python will be garbage collected once nothing points to them, so you need not worry. Otherwise, you should checkout some of the answers in this other SO question: Python object deleting itself.

You could try:

def kill():
if self.health < 0:
del self

Self-deleting class in Python

del DestructMe

This is not deleting the class. This is deleting the name that happens to refer to the class. If there are no other references to the class (and that includes the name you just deleted, any module that's ever imported the class, any instances of the class, and any other places where the class might happen to be stored), then the garbage collector might delete the class when you gc.collect().

Now an instance always knows its own class, via the __class__ attribute. It makes little sense to delete self.__class__, because then what would we be left with? An instance with no class? What can we do with it? We can't call methods on it since those are defined on the class, and we can't do anything object-like on it since it's no longer an instance of object (a superclass of the class we just removed). So really we have a sort of silly looking dictionary that doesn't even do all of the dict things in Python. Hence, disallowed.

You cannot delete data in Python. That's the garbage collector's job. There is no Python equivalent of C's free or C++'s delete. del in Python deletes bindings or dictionary entries. It does not remove data; it removes pointers that happen to point to data.

destroy object of class python

Think of it that way: you're asking a class to self-destruct using an inner method, which is kind of like trying to eat your own mouth.

Luckily for you, Python features garbage collection, meaning your class will be automatically destroyed once all of its references have gone out of scope.

If you need to do something specific when the instance is being destroyed, you can still override __del__() which will kinda act like a destructor. Here's a silly example:

class SelfDestruct:
def __init__(self):
print("Hi! I'm being instanciated!")

def __del__(self):
print("I'm being automatically destroyed. Goodbye!")

def do_stuff(self):
print("I'm doing some stuff...")

Now, try instanciating this class in a local scope (such as a function):

def make_a_suicidal_class():
my_suicidal_class = SelfDestruct()
for i in range(5):
my_suicidal_class.do_stuff()
return None

Here, the lifespan of the object is bound by the function. Meaning it'll be automatically destroyed once the call is completed. Thus the output should look like:

>>> make_suicidal_class()
"Hi! I'm being instanciated!"
"I'm doing some stuff..."
"I'm doing some stuff..."
"I'm doing some stuff..."
"I'm doing some stuff..."
"I'm doing some stuff..."
"I'm being automatically destroyed. Goodbye!"
>>>

If your class was instanciated in a global scope, then it won't be destroyed until your program ends.

Also, it should be noted that manually calling the __del__() destructor does NOT actually destroy the object. Doing this:

foo = SelfDestruct()
foo.__del__()
foo.do_stuff()

Results is this output:

"Hi! I'm being instanciated!"
"I'm being automatically destroyed. Goodbye!"
"I'm doing some stuff..."

ergo, the instance still has a pulse... If you really need to prevent the instance from being referenced again in the current scope, you have to call del foo to do so.

Though as previously stated, Python actually reference-counts classes and variables. So if your class object is used elsewere, invoking del foo will not actually release it from memory.

Here's an exhaustive explanation in the python docs
https://docs.python.org/2.5/ref/customization.html

"del x" doesn't directly call x.del() -- the former decrements the reference count for x by one, and the latter is only called when x's reference count reaches zero.

Long story short: Don't think about it! Let python deal with memory management. The whole point of garbage collection is to stop worrying about the lifespan of your variables!

Can you make an objects that deletes itself in Django?

Just make a filter that prevents retrieving expired VerificationTokens:

from datetime import timedelta
from django.db.models.functions import Now

VerificationToken.objects.filter(
date_created__gte=Now()-timedelta(minutes=10)
)

You can also make a manager such that VerificationToken.objects is a manager that only contains non-expired tokens:

from datetime import timedelta
from django.conf import settings
from django.db.models.functions import Now

class VerificationTokenManager(models.Manager):

def get_queryset(self):
return super().get_querset().filter(
date_created__gte=Now()-timedelta(minutes=10)
)

class VerificationToken(models.Model):
user = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE
)
code = models.CharField(max_length=4)
date_created = models.DateTimeField(auto_now_add=True, db_index=True)
objects = VerificationTokenManager()

you can then make a management command [Django-doc] that you for example run through cron, or some other scheduling task that removes expired VerificationTokens with:

# app_name/management/commands/remove_expired_tokens.py

from datetime import timedelta
from django.core.management.base import BaseCommand
from django.db.models.functions import Now
from app_name.models import VerificationToken

class Command(BaseCommand):
help = 'Remove expired verification tokens'

def handle(self, *args, **options):
VerificationToken._base_manager.filter(
date_created__lt=Now()-timedelta(minutes=10)
).delete()


Note: It is normally better to make use of the settings.AUTH_USER_MODEL [Django-doc] to refer to the user model, than to use the User model [Django-doc] directly. For more information you can see the referencing the User model section of the documentation.

How do i make this container delete itself?

You can't. I just spent some time digging through the Python source and ctypes documentation to ironically show how one might really delete (aka Py_DECREF until deallocated) an object until I gave up. The point is, you don't really want to do this. Python manages its own memory for a reason. Sure, it gives you access to things like weak references, but in no case will Python break a strong reference.

What you are proposing is to have an object reach into the environments of every bit of code loaded into the Python interpreter to rip out any references to itself. weakref has to rip out references too, but it only has to remove the references from the weakref object; it doesn't have to touch the object holding a reference to the weakref. To remove a reference in the way you propose would be at least invasive and most likely impossible.

To see why it would be impossible, consider how one might write a Python module in C that defines a type. Each instance of the object is going to hold some PyObject pointers to things it cares about. Some of these might be exposed to Python through properties, while others might remain internal. Suppose one of these internal references referenced one of your Foo objects. For it to 'delete' itself, it would have to reach into our C type and NULL out the reference. But to Python code, the C struct defining the object is opaque. If you dug into it with ctypes, you could inspect the bytes, but who's to know whether some sequence of bytes is a pointer to your object or an int that just happens to have the same value as the address of your object? You can't, at least without knowing implementation details of that type. And you can't handle every case, because someone can add another case just by importing another module written in C. You can't anticipate everything.

So what can you do? If you're deadset on doing something like this, you can mimic weakref's interface. Basically, make a new class that holds a reference to your class; to avoid ambiguity, I'll call this a fakeref. When it's called, it returns the instance of your class. Your class holds weak references1 to all of its fakerefs. Whenever your Foo class wants to delete itself, loop over the fakerefs, Noneing out the references to the Foo. Voilà; your class can 'delete' itself as desired and all of the fakerefs will now return None. But just as with weakrefs, storing the result of a call will make it a strong reference again, and your class will not be able to delete itself in the manner you desire.

All this said, I don't think you've presented a good enough case for why this is necessary. All you've said is that "there's no reason for it to stay in memory". Well, there is: it needs to be there for the objects that reference it. If, at some point in time, it becomes useless, then your objects shouldn't be holding a reference to it. When the objects referencing it don't care about it any more, they should remove those references. Then Python will clean it up with no further intervention on your part.


1 If you don't want to rely on weak references, your fakeref can implement __del__ and remove itself from your Foo instance it holds a reference to (if not None).



Related Topics



Leave a reply



Submit