Python Intermediate: How to use Destructors in Python

Destructors in Python

When an object is destroyed, destructors are called. Destructors are not as crucial in Python as in C++ because Python has a garbage collector that automatically handles memory management. In Python, the del() method is referred to as a destructor. It is invoked when all references to an object have been removed, i.e., when an object is garbage collected. A reference to an object is also deleted when the object is no longer referenced or when the program terminates.

Here’s a simple destructor example. Because we used the del keyword to delete all references to the object ‘stu_object’. The destructor was automatically invoked. The destructor was called when the program finished or when all references to the object were deleted, i.e. when the reference count reached zero, not when the object was no longer in scope.

Using the __del__ Method

Example:

class Students:
 
   def __init__(self):
       print('Student created.')
 
   def __del__(self):
       print('Destructor called, Student deleted.')
 
stu_object = Students()
del stu_object

Output:

Student created.
Destructor called, Student deleted.

This example explains the previously mentioned note. Take note that the destructor is called after the ‘Program End…’ message is printed.

Example:

class Students:
 
   def __init__(self):
       print('Student created')
 
   def __del__(self):
       print("Call the Destructor")
 
def making_object():
   print('Making an object')
   stu_object = Students()
   print('This function has been ended')
   return stu_object
 
print('Calling Making_Object() function...')
object_del = making_object()
print('Program End...')

Output:

Calling Making_Object() function...
Making an object
Student created
This function has been ended
Program End...
Call the Destructor

Function del is the inverse of function new, just as Destructor is the inverse of Constructor. Because the function that creates the object is new. When an object’s reference count reaches zero, the del method is called. Because reference counting is performed, it is not necessary for an object’s del method to be called if it is no longer in scope. When the reference count reaches zero, the destructor method is called.

Reference in Circulars

Circular referencing describes a situation in which two objects refer to one another. When both of these objects become unreferenced, Python is unsure which to destroy first, and to avoid an error, it does not destroy either of them.

Here’s an example of circular referencing in action:

Example:

class Chickens_born():
   def __init__(self, id, bar):
       self.id = id
       self.friend = bar
       print ('Red Chicken', self.id+4, 'born')
 
   def __del__(self):
       print ('Red Chicken', self.id-3, 'died')
 
 
class Chickens_die():
   def __init__(self, id):
       self.id = id
       self.friend = Chickens_born(id, self)
       print ('White Chicken', self.id+3, 'born')
 
   def __del__(self):
       print ('White Chicken', self.id-2, 'died')
 
 
Chickens = Chickens_die(7)
# print(Chickens)

Output:

Red Chicken 11 born
White Chicken 10 born
White Chicken 5 died
Red Chicken 4 died

Exceptions

In object-oriented programming, the destructor is only called when an object is successfully created because if an exception occurs in the constructor, the object is destroyed by the constructor itself.

However, in Python, if an exception occurs in the init method while initializing the object, the method del is also called. As a result, even if the object was never properly initialized, the del method will attempt to empty all resources and variables, which may result in another exception. How to handle an Exception, you can check Python Exception Handling.

Example:

class Error_example():
   def __init__(self, item):
       if item == 0:
           raise Exception()
       self.item = item
      
   def __del__(self):
       print (self.item)
 
Error_object = Error_example()
del Error_object

Output:

Exception ignored in: <function Error_example.__del__ at 0x7f22a0cbd0d0>
Traceback (most recent call last):
 File "/Python/error_exception.py", line 8, in __del__
   print (self.item)
AttributeError: 'Error_example' object has no attribute 'item'
Traceback (most recent call last):
 File "/Python/error_exception.py", line 10, in <module>
   Error_object = Error_example()
TypeError: __init__() missing 1 required positional argument: 'item'

The importance of destructors in Python is that they allow the programmer to ensure that all resources used by an object are properly cleaned up when the object is no longer needed. This can be particularly important when dealing with objects that use system resources such as files or network connections, as failing to release these resources can lead to problems such as memory leaks or resource exhaustion.

By defining a destructor method in a Python class, the programmer can ensure that any resources used by objects of that class are properly released when the objects are no longer needed. This can help to prevent problems such as memory leaks or resource exhaustion, and can also make it easier to write more reliable and robust code.

Share The Tutorial With Your Friends
Twiter
Facebook
LinkedIn
Email
WhatsApp
Skype
Reddit

Check Our Ebook for This Online Course

Advanced topics are covered in this ebook with many practical examples.