Reputation: 1548
I would like to delete an instance of my object after executing a function so that no python script can access this instance anymore.
Here is my code:
class MyClass():
def myFunc(self):
...
del self
myClass = MyClass()
myClass.myFunc()
print(myClass) # Supposed to raise an error because myClass is supposed to be deleted but that's not the case
What's going wrong?
Upvotes: 1
Views: 2844
Reputation: 286
Since you can't delete objects in python and only delete the appearance of variables in the namespace. I would recommend just raising an error once the function is called once. Since you want an error to occur after its run.
class MyClass():
def myFunc(self):
...
counter += 1
del self
counter = 0
# Check if the function has been run once and then raise exception
if counter > 0:
raise exception("Instance cannot be used")
myClass = MyClass()
myClass.myFunc()
print(myClass)
I hope this still does what you anticipate but the del
function only deletes the appearance of variable in the namespace and not allowing you to reference it anymore (But its not being deleted).
Upvotes: 1
Reputation: 114240
You misunderstood how del
works. It does not remove objects. It removes names.
For example, say you have
>>> x = [1, 2, 3]
>>> y = x
>>> z = x
All three names, x
, y
, z
refer to the same list object. Now delete x
:
>>> del x
>>> x
NameError: name 'x' is not defined
It would make no sense for y
and z
to raise a NameError
after this. Imagine especially if y
and z
were references in a different function or module. Having del x
make other references disappear would lead to some very unexpected and undesirable behaviors.
So under normal circumstances, you can't quite do what you want to do. Your current method is just removing the name self
in the local namespace of the method itself. It can not easily modify the global namespace.
That being said, you can write a function that removes a name from the global namespace. For example:
class MyClass:
def myFunc(self, name):
del globals()[name]
myInst = MyClass()
myInst.myFunc('myInst')
Now, if you attempt to access myInst
, the name will be gone in the script. This is a bad idea, and likely won't delete the object at all anyway. If you had another reference to myInst
, e.g. in a list
, dict
or direct assignment to another name, that reference would persist, and so would the object itself.
A much better approach, as suggested in the comments, is to mark the instance as unusable. For example, you can do something like
class MyClass:
def __init__(self):
self.useable = True
def my_func(self):
self._check_useable()
# do your thing...
self.useable = False
def other_func(self, *args):
self._check_useable()
# Do stuff to args ...
def _check_useable(self):
if not self.useable:
raise ValueError('Class is not useable!')
There are more robust ways of implementing the flag to make it less accessible to the casual user, but they basically follow the same pattern.
Upvotes: 2