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 VerificationToken
s:
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 VerificationToken
s 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 theUser
model [Django-doc] directly. For more information you can see the referencing theUser
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 fakeref
s. Whenever your Foo
class wants to delete itself, loop over the fakeref
s, None
ing out the references to the Foo
. Voilà; your class can 'delete' itself as desired and all of the fakeref
s will now return None
. But just as with weakref
s, 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
Too Many Values to Unpack Calling Cv2.Findcontours
How to Merge Images into a Canvas Using Pil/Pillow
How to Get the Domain Name of My Site Within a Django Template
How to Create a Numpy Array of Arbitrary Length Strings
How to Use Hex() Without 0X in Python
Fitting a Normal Distribution to 1D Data
How to Copy Inmemoryuploadedfile Object to Disk
How to Return a String from a Regex Match in Python
How to Find the First Key in a Dictionary
Default Filter in Django Admin
Handling Urllib2's Timeout? - Python
Format String Unused Named Arguments
How to Change the String Representation of a Python Class
Use Scipy.Integrate.Quad to Integrate Complex Numbers
Builtins.Typeerror: Must Be Str, Not Bytes
JSON.Loads Allows Duplicate Keys in a Dictionary, Overwriting the First Value