Suppose someone didn't know what the difference was between __del__
and __delete__
? Write an explanation.
object.__del__(self)
: Called when the instance is about to be destroyed. This is also called a finalizer or (improperly) a destructor. If a base class has a
__del__()
method, the derived class's__del__()
method, if any, must explicitly call it to ensure proper deletion of the base class part of the instance.
I think this means that my_object.__del__
will get called by CPython's garbage collector after the reference count for my_object
drops to zero.
object.__delete__(self, instance)
: Called to delete the attribute on an instance
instance
of the owner class.
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).
del
statement : "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..." delattr
built-in function. From the docs, "The function deletes the named attribute, provided the object allows it. For example, delattr(x, 'foobar')
is equivalent to del x.foobar
."object.__delattr__(self, name)
is called when attribute deletion is attempted. According to the docs, "This should only be implemented if del obj.name
is meaningful for the object." Thus, defining a user class with the method MyClass.__delattr__
enables custom behavior when eg the statement del my_object.an_attr
is invoked, or (equivalently) when delattr(my_object, 'an_attr')
is called.object.__delitem__(self, key)
is "Called to implement deletion of self[key]
." Thus, defining a user class with the method MyClass.__delitem__
enables custom behavior when eg the statement del my_object[a_key]
is invoked.__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__
__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)
__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)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.