I would like to reliably call the __del__
method of an object immediately when it gets deleted. I am aware that this has been asked for python 2, but the documentation of python 3 claims that the __del__
method is called when the reference count reaches 0. However, this does not seem to be the case with my program
import time
class MyClass:
object_list = []
def __init__(self):
MyClass.object_list.append(self)
print("object initialized")
def __del__(self):
print("executing cleanup steps")
MyClass.object_list.remove(self)
a = MyClass()
b = MyClass()
c = MyClass()
print(len(MyClass.object_list))
del b
time.sleep(1)
print("sleep finished")
print(len(MyClass.object_list))
What I want to achieve is to remove b
from the object_list
immediately when it is destroyed and also make the variable b
inaccessible. So simply calling b.__del__()
is not enough, I would need to also render b
inaccessible.
Note: running first b.__del__()
and then del b
will lead to complaints when exiting the python interpreter.
Interestingly enough, a very similar program seems to call b.__del__()
immediately when del b
is executed.
import time
class MyClass:
counter = 0
def __init__(self, value):
self.value = value
print("object initialized")
MyClass.counter+=1
def __del__(self):
print("executing cleanup steps")
MyClass.counter-=1
a = MyClass(5)
b = MyClass(6)
c = MyClass(7)
print(MyClass.counter)
del b
time.sleep(1)
print("sleep finished")
print(MyClass.counter)
EDIT
@Pranav Hosangadi pointed out that there is still a reference to the object in the object_list
. What a shameful oversight of mine. Now I came up with a workaround by calling first b.__del__()
and then del b
, but it is a two step process. I would like to have it in one step, if possible.
import time
class MyClass:
object_list = []
def __init__(self, value):
self.value = value
MyClass.object_list.append(self)
print("object initialized")
def __del__(self):
print("executing cleanup steps")
try:
MyClass.object_list.remove(self)
except:
pass
a = MyClass(1)
b = MyClass(2)
c = MyClass(3)
print(len(MyClass.object_list))
b.__del__()
del b
time.sleep(1)
print("sleep finished")
print(len(MyClass.object_list))