Everything you Should Know About Destructors in Python

learn how to create a destructor in Python and discover how a destructor works.

Picture of Nsikak Imoh, author of Macsika Blog
The text Everything you Should Know About Destructors in Python on a plain background.
The text Everything you Should Know About Destructors in Python on a plain background.

Table of Content

A destructor is a special method that is called when an object gets destroyed.

Destructors are called when an object gets destroyed.

In Python, destructors are not needed as much as in C++ because Python has a garbage collector that handles memory management automatically.

In this lesson, you will learn how to create a destructor in Python, the use of __del__() method, and discover how a destructor works in Python.

What is a Destructor in OOP?

A destructor is a special method that is called when an object is deleted or destroyed.

A destructor is used to clean up before destroying the object, such as closing database connections, I/O, or file management.

Python has a garbage collector that handles memory management automatically.

This garbage collector cleans up the memory when an object goes out of scope.

But it's not just memory that has to be freed when an object is destroyed.

We must release or close the other resources of the object we were using, such as files, database connections, buffer, or cache.

All of those cleanup tasks are performed using a destructor in Python.

The destructor is handled automatically in Python and gets called when an object goes out of scope or the reference counter of the object reaches 0.

In Python, The special method __del__() is used to define a destructor.

For example, when we execute del object_name destructor gets called automatically and the object gets garbage collected.

Characteristics of a Destructor in Python

  • The __del__ method is called for each object when it is no longer referenced.
  • The __del__ method for each object is called in the order it was instantiated.
  • The reference count for that object becomes zero when the application ends.
  • All references to an object can also become zero when we delete it manually using the del keyword.
  • The destructor will not be invoked when we simply delete the reference to an object. It is only invoked when all references to the objects are deleted.

How a Destructor is Created in Python Using the __del__() Method

The method __del__() is used as

A destructor in Python is created using the __del__() dunder method.

Like a constructor, it will be implicitly invoked when not explicitly stated.

It is usually invoked **when all references to the object have been deleted and the object is about to be destroyed and for garbage collection to take place.

Syntax of destructor declaration

def __del__(self):
    # body of a destructor
Highlighted code sample.
  • def: This is the keyword used to define a function.
  • __del__() Method is a special method that is called when all references to the object are deleted and the object is about to be destroyed.
  • self: The self parameter refers to the current object. It is always the first parameter in every instance method.

Example of Destructor in Python When the Object is no Longer Referenced

class Car:
	# constructor
    # initialize instance variable
    def __init__(self, model, brand, color):
        # instance variables
        self.model = model
        self.brand = brand
        self.color = color
        print('Object is initialized')

    def info(self):
        print('Model:', self.model, 'Brand:', self.brand, 'Color:', self.color)

	# destructor
    def __del__(self):
        print('Destructor method is called for', self.model)
        print('Object destroyed')
        
# Instance of tesla accessing instance methods and variable
tesla = Car("Y", "Tesla", "Black")
tesla.info()

toyota = Car("Camry", "Toyota", "Black")
toyota.info()
Highlighted code sample.

Output

Object is initialized
Model: Y Brand: Tesla Color: Black
Object is initialized
Model: Camry Brand: Toyota Color: Black
Destructor method is called for Y
Object destroyed
Destructor method is called for Camry
Object destroyed
Highlighted code sample.

From the output, we can see that the __del__() method gets automatically called for each object when there's no longer any reference to the object.

The constructor of all objects and their references will first be initiated before the destructor is executed.

The __del__ method is called for each object in the order it was instantiated.

The reference count for that object becomes zero when the application ends.

Example of Destructor in Python When the Reference to the Object is Deleted

Access the class above in the following format

tesla = Car("Y", "Tesla", "Black")
tesla.info()

del tesla

toyota = Car("Camry", "Toyota", "Black")
toyota.info()
Highlighted code sample.

Output

Object is initialized
Model: Y Brand: Tesla Color: Black
Destructor method is called for Y
Object destroyed
Object is initialized
Model: Camry Brand: Toyota Color: Black
Destructor method is called for Camry
Object destroyed
Highlighted code sample.

From the output, we can see that the __del__() method for the tesla object is called immediately, and no longer waits for other object initialization to be completed.

Example of Destructor in Python When All Reference to the Object is Not Deleted

# Instance of tesla accessing instance methods and variable
tesla = Car("Y", "Tesla", "Black")
tesla.info()
tesla_ref = tesla # <--- Reference to tesla object
del  tesla

toyota = Car("Camry", "Toyota", "Black")
toyota.info()
Highlighted code sample.

Output

Object is initialized
Model: Y Brand: Tesla Color: Black
Object is initialized
Model: Camry Brand: Toyota Color: Black
Destructor method is called for Y
Object destroyed
Destructor method is called for Camry
Object destroyed
Highlighted code sample.

From the output above, you will notice that the execution is different and similar to the first, despite calling del tesla.

This is because the tesla object is referenced by another variable tesla_ref, hence, the tesla object will not be deleted until all reference to it is deleted.

Or, the reference count for that object becomes zero when the application ends, and the __del__() method is called.

To call the destructor for each object in order rather than wait for the application to end, delete all references:

# Instance of tesla accessing instance methods and variable
tesla = Car("Y", "Tesla", "Black")
tesla.info()
tesla_ref = tesla # <--- Reference to tesla object
del  tesla, tesla_ref
toyota = Car("Camry", "Toyota", "Black")
toyota.info()
Highlighted code sample.

Output

Object is initialized
Model: Y Brand: Tesla Color: Black
Destructor method is called for Y
Object destroyed
Object is initialized
Model: Camry Brand: Toyota Color: Black
Destructor method is called for Camry
Object destroyed
Highlighted code sample.

Situations that Prevent the Python Destructor from Executing

The __del__ dunder method is not a perfect solution to clean up a Python object when it is no longer required.

In Python, the destructor does not work in the following situations.

  1. Circular referencing
  2. Exception when the constructor is called

How does Circular Referencing Affect a Destructor?

The __del()__() doesn't work correctly in the case of circular referencing.

Circular referencing occurs when two objects refer to each other.

This is because Python doesn't know which object to destroy first when both objects go out of scope.

This simply means that the garbage collector does not know the order in which the object should be destroyed, so it doesn't delete them from memory.

As a result, to avoid unwanted errors, the destructor is not called on any of them.

Even though the destructor always runs when an object goes out of scope, or its reference count reaches zero, the objects involved in circular reference remain in memory until the program ends.

Example of how Circular Referencing affects a Destructor:

import time

class Vehicle():
    def __init__(self, id, car):
        self.id = id;
        # saving reference of Car object
        self.dealer = car;
        print('Vehicle', self.id, 'created');

    def __del__(self):
        print('Vehicle', self.id, 'destroyed');


class Car():
    def __init__(self, id):
        self.id = id;
        # saving Vehicle class object in 'dealer' variable
        # Sending reference of Car object ('self') for Vehicle object
        self.dealer = Vehicle(id, self);
        print('Car', self.id, 'created')

    def __del__(self):
        print('Car', self.id, 'destroyed')


# create a car object
c = Car(12)
# delete car object
del c
# ideally destructor must execute now

# to observe the behavior
time.sleep(8)
Highlighted code sample.

Output:

Vehicle 12 created
Car 12 created
Highlighted code sample.

In the above example, ideally, both Vehicle and Car objects remain in memory and only became destroyed by the garbage collector when they go out of scope.

How an Exception in the Constructor affects a Destructor in Python

In many programming languages that implement OOP, if there's an exception in the constructor while initializing the object, the constructor destroys the object.

Likewise, in Python, if any exception occurs in the init method while initializing the object, the method del gets called.

Even though the object was never initialized correctly, the del method will try to empty all the resources and, in turn, may lead to another exception.

Example of how an exception in the constructor affects a destructor in Python:

class Vehicle:
    def __init__(self, speed):
        if speed > 240:
            raise Exception('Not Allowed');
        self.speed = speed;

    def __del__(self):
        print('Release resources')

# creating an object
car = Vehicle(350);
# to delete the object explicitly
del car
Highlighted code sample.

Output:

Traceback (most recent call last):
Release resources
Exception: Not Allowed
Highlighted code sample.

Wrap Off

In this lesson, a destructor is used to perform the clean-up activity before destroying the object, such as closing database connections, I/O, and file management.

In Python, we use the __del__() method to perform a clean-up task before deleting the object.

A destructor is called when an object is deleted or destroyed.

If you learned from this tutorial, or it helped you in any way, please consider sharing and subscribing to our newsletter.

Please share this post and for more insightful posts on business, technology, engineering, history, and marketing, subscribe to our newsletter.

Get the Complete Code of Object Oriented Programming in Python on Github.

Connect with me.

Need an engineer on your team to grease an idea, build a great product, grow a business or just sip tea and share a laugh?