Suppose someone didn't know what the difference was between __del__ and __delete__? Write an explanation.
What is the difference between `__del__` and `__delete__`?
7.9k Views Asked by Toothpick Anemone AtThere are 2 best solutions below
On
__del__ is called when you delete an object and __delete__ is sometimes called when you delete an attribute of an object.
del x.my_num # __delete__
del x # __del__
ABOUT __del__:
The following code shows when __del__ gets called:
class MyClass:
def __init__(self):
file = open("really_cool_file.txt", "w+")
self._f = file
def __del__(self):
print("closing any open files ")
self._f.close()
my_instance = MyClass()
del my_instance
If my_instance is the last label pointing to the data, then del my_instance calls MyClass.__del__(my_instance)
Technically, del my_instance only deletes the label my_instance. Imagine people at a party all wearing names tags. Sometimes a person has 6 or 7 names tags on simultaneously, and other times, they only have one. Python will kick anyone out of the party who is not wearing at least one name tag. MyClass.__del__(my_instance) gets called when the last name-tag/label is removed from a piece of data.
The code above shows an example of when we make sure to close an open file. Another example might be to count of the number active instances of a given class:
class Klass:
count = 0
# `count` belongs to the class
# instances do not each get their own copy of `count`
def __init__(self):
type(self).count += 1
self.instance_var = "I belong to instances"
def __del__(self):
type(self).count -= 1
obj = Klass()
print(obj.count)
ABOUT __delete__
Unlike __del__, __delete__ has to do with descriptors.
The code below describes the behavior of obj.my_var or getattr(obj, “my_var”)
class Klaus: def getattribute(self, attrname): try: attribute = attrname from instance Klaus except AttributeError: attribute = attrname from class Klaus
# Begin code for handling "descriptors"
if hasattr(attribute, '__get__'):
attr = attribute.__get__(self, Klaus)
# End code for handling "descriptors"
return attribute
If my_var is a descriptor, then following two lines of code equivalent:
x = obj.my_var
x = Klass.my_var.__get__(obj, "my_var")
Just as __getattribute__ checks whether the attribute has a __get__ method or not, __delattr__ will check whether the attribute has a __delete__ method or not.
def __delattr__(self, name):
attribute = getattr(self, name)
if hasattr(attribute, "__delete__"):
attribute.__delete__(self)
else:
del self.__dict__[name]
You can see when __delete__ gets called by viewing the following code:
class desc:
def __delete__(descriptor, instance_of_Klaus):
print("attribute was deleted")
class Klaus:
d = desc()
def __init__(self):
pass
my_instance = Klaus()
del my_instance.d
When dealing with descriptors, the following lines of code are all equivalent:
del my_instance.d
delattr(my_instance, "d")
Klaus.d.__delete__(my_instance)
object.__del__(self):I think this means that
my_object.__del__will get called by CPython's garbage collector after the reference count formy_objectdrops to zero.object.__delete__(self, instance):The
__delete__dunder method is related to python's notion of descriptors; a descriptor is "any object which defines the methods__get__(),__set__(), or__delete__()." Descriptors can be used to implement custom behavior for attribute lookup/assignment/deletion (via__get__/__set__/__delete__, respectively).See also:
delstatement: "Deletion of a name removes the binding of that name from the local or global namespace... Deletion of attribute references, subscriptions and slicings is passed to the primary object involved..."delattrbuilt-in function. From the docs, "The function deletes the named attribute, provided the object allows it. For example,delattr(x, 'foobar')is equivalent todel x.foobar."object.__delattr__(self, name)is called when attribute deletion is attempted. According to the docs, "This should only be implemented ifdel obj.nameis meaningful for the object." Thus, defining a user class with the methodMyClass.__delattr__enables custom behavior when e.g. the statementdel my_object.an_attris invoked, or (equivalently) whendelattr(my_object, 'an_attr')is called.object.__delitem__(self, key)is "Called to implement deletion ofself[key]." Thus, defining a user class with the methodMyClass.__delitem__enables custom behavior when e.g. the statementdel my_object[a_key]is invoked.