A destructor is a special method that is called when an object is about to be destroyed. In Python, del() is commonly referred to as a destructor, although the Python documentation describes it more precisely as a finalizer.Â
- Can be used to perform cleanup operations associated with an Object.
- Should not normally be used for important resources management.
- Does not guarantee exactly when an object will be finalized.
Example:
class Employee:
def __init__(self):
print('Employee created.')
def __del__(self):
print('Destructor called, Employee deleted.')
obj = Employee()
del obj
Output
Employee created. Destructor called, Employee deleted.
Explanation:
- Employee class defines a constructor (init) and a destructor (del).
- When the Employee object is created, init() runs and prints "Employee created".
- del obj statement removes the reference to the object.
- Once the object is no longer referenced, del() is called and prints "Destructor called, Employee deleted."
- Destructor is mainly used for cleanup tasks before an object is destroyed.
Syntax
class ClassName:
def __del__(self):
# cleanup code
pass
del Statement vs del() Method
del statement and del() method are not the same. This distinction is important because an object may have multiple references.
class Demo:
def __del__(self):
print("Object finalized")
obj1 = Demo()
obj2 = obj1
del obj1
print("First reference removed")
del obj2
print("Second reference removed")
Output
First reference removed Object finalized Second reference removed
Explanation:
- obj1 and obj2 refer to the same object.
- Removing obj1 does not destroy the object because obj2 still refers to it.
- After obj2 is removed, no references remain.
- Object can then be finalized.
Destructor and Garbage Collection
Garbage collection is responsible for detecting and reclaiming objects that are no longer accessible, particularly objects involved in reference cycles. Python's memory-management system uses reference counting along with cyclic garbage collection.
For more information, refer to Garbage Collection in Python.
import gc
class Node:
def __init__(self):
self.reference = None
def __del__(self):
print("Node finalized")
node1 = Node()
node2 = Node()
node1.reference = node2
node2.reference = node1
del node1
del node2
gc.collect()
Output
Node finalized Node finalized
Explanation:
- Two object reference each other.
- Simply removing node 1 and node 2 does not immediately make their reference counts zero.
- Garbage collector can detect such unreachable cycles and reclaim them.
- Modern python supports finalization of objects involved in such cycles.
Destructor with Multiple References
Object can have several references pointing to it. Its finalizer is not triggered merely because one reference is removed.
class Student:
def __del__(self):
print("Student object destroyed")
student1 = Student()
student2 = student1
del student1
print("student1 deleted")
del student2
print("student2 deleted")
Output
student1 deleted Student object destroyed student2 deleted
Explanation:
- Destructor runs only after the final references to the object has been removed.
Destructor for Cleanup
It can be useful for simple cleanup actions associated with an object.
class FileManager:
def __init__(self, filename):
self.filename = filename
print("Object created")
def __del__(self):
print("Cleaning up:", self.filename)
file = FileManager("data.txt")
del file
Output
Object created Cleaning up: data.txt
Object Resurrection
It's an unusual behavior of del(). A finalizer can create another references to the object, preventing its destruction.
# Python program to illustrate destructor
class A:
def __init__(self, bb):
self.b = bb
class B:
def __init__(self):
self.a = A(self)
def __del__(self):
print("die")
def fun():
b = B()
fun()
Output
die
Explanation:
- Finalizer creates new reference through saved_object, so the object can remain alive.
- This behavior is called object resurrection and is generally not recommend.
- In current CPython, a resurrected object's del() is called only once.
del() In Inherietance
When a derived class defines del(), Python does not automatically call the base class's del() method.
class Parent:
def __del__(self):
print("Parent cleanup")
class Child(Parent):
def __del__(self):
print("Child cleanup")
super().__del__()
obj = Child()
del obj
Output
Child cleanup Parent cleanup
Explanation:
- If the parent also needs cleanup, the child should explicitly call the parent implementation.
- Python's documentation specifically notes that a derived class must explicitly call the base class's del() when necessary.
Destructor vs Constructor in Python
Constructors and destructors server different purposes.
| Constructor | Destructor |
|---|---|
| Uses init() | Uses del() |
| Initializes an object | Performs finalization |
| Runs during object initialization | Runs when the object is about to be destroyed |
| Used to set the initial state | Used for cleanup-related actions |
| Normally predictable during object creation | Destruction timing may not be predictable |