Python

P
PythonHub
Progress 0%

Python

  • Home
  • History of Python
  • Applications of Python
  • Introduction To Python
    • What is Python
    • Character Set
    • Tokens in Python
    • Python Execution Mode
    • Variable And Identifiers
    • Data Types in Python
    • Operators And Expressions
    • Constants in Python
    • Assignment Statement
    • Input / Output in Python
    • Simple Python Scripts
    • Namespace in Python
    • 📝 Assignments
  • Operators in Python
    • Arithmetic Operators
    • Assignment Operators
    • Shorthand Assignment Operators
    • Relational Operators
    • Logical Operators
    • Bitwise Operators
    • Special Operators
    • 📝 Assignments
  • Input Output in Python
    • Accept Input
    • Output Formatting
    • 📝 Assignments
  • Conditional Statement
    • Decision Making
    • if Statement
    • IF-ELSE STATEMENT
    • IF-ELSE LADDER
    • NESTED IF-ELSE
    • Short Hand IF-ELSE
    • 📝 Assignments
  • Loops
    • Introduction to Loops
    • While Loop
    • Nested While Loop
    • 📝 While Loop Assignments
    • For Loop
    • For Loop Examples
    • Nested For Loop
    • Nested For Loop Examples
    • Infinite While Loops
    • Infinite For Loops
    • Break, Continue and Else in Loops
    • Difference Between For and While Loop
    • For Each Loop
    • 📝 For Each Assignments
    • 📝 All Loops Assignments
  • List
    • List in Python
    • Access List Elements
    • List Functions
    • Iterate (Loop) List
    • List Comprehension
    • 📝 Assignments
  • Tuple
    • Tuple in Python
    • Access Tuple Elements
    • Tuple Functions
    • Iterate (Loop) Tuple
    • Unpack Tuple
    • Tuple Comprehension
    • 📝 Assignments
  • Set
    • Set in Python
    • Access Set Elements
    • Set Methods
    • Iterate (Loop) Set
    • Pack/Unpack Set
    • Set Comprehension
    • 📝 Assignments
  • Dictionary
    • Dictionary
    • Access Dictionary Items
    • Dictionary Methods
    • Iterate (Loop) Dictionary
    • Formatting Dictionaries
    • Nested Dictionaries
    • Dictionary Comprehension
    • 📝 Assignments
  • Diff List Tuple Set Dictionary
    • List vs Tuple
    • List vs Set
    • List vs Dictionary
    • Tuple vs Set
    • Tuple vs Dictionary
    • Dictionary vs Set
    • 📝 Assignments
  • Exception
    • Error vs Exception
    • Types of Exception
    • Exception Handling
    • User Defined Exception
    • Logging Exception
    • 📝 Assignments
  • Functions
    • Introduction to Functions
    • Modular Programming
    • Types of Functions
    • Inbuilt Functions
    • Need For User-Defined Function
    • Elements of User Defined Function
    • Function Arguments
    • Nesting of Functions
    • Recursion
    • Global Local and Non Local
    • Python Lambda Functions
    • 📝 Assignments
  • Python Module
    • Introduction to Module
    • Inbuilt Modules in Python
    • User Defined Module
    • 📝 Assignments
  • File Handling
    • Introduction to Files
    • Create File
    • Read Files
    • Write to File
    • Rename File
    • Copy File
    • Move File
    • List Files in Directory
    • Binary Files
    • Zipping and Unzipping Files
    • 📝 Assignments
  • Strings
    • Basics of Strings
    • String Special Operators
    • String Formatting Operators
    • String Methods
    • 📝 Assignments
  • Regular Expressions
  • Python OOPS
    • Basics of Object Oriented
    • What are Classes and Objects?
    • Creating Class and Object
    • OOP vs Procedural Programming
    • Difference Between Classes and Objects
    • Constructors
    • Destructor
    • Built Class Methods and Attributes
    • Class and Instance Variables
    • Inheritance in Python
    • Single Inheritance
    • Multiple Inheritance
    • Multilevel Inheritance
    • Hierarchical Inheritance
    • Hybrid Inheritance
    • Abstraction
    • Method Overriding
    • Abstract Method
    • Interfaces in Python
    • Abstract Class vs Interface
    • Public, Private and Protected
    • Overloading vs Overriding
    • Inheritance vs Composition
    • Encapsulation
    • Polymorphism
    • Inner Classes
    • 📝 Assignments
  • Advanced Python
    • Iterator in Python
    • Generator in Python
    • Decorator in Python
    • Type Hints in Python
    • Async/Await Programming
    • Dataclasses in Python
    • Context Managers in Python
    • Property Decorator in Python
    • __slots__ in Python
    • Enums in Python
    • Walrus Operator in Python
    • Match-Case in Python
    • 📝 Assignments
  • Python Standard Library
    • Collections Module
    • Itertools Module
    • Functools Module
    • Datetime Module
    • JSON Module
    • OS Module
    • Sys Module
    • Random Module
    • Math Module
    • 📝 Assignments
  • Python Testing
    • Unit Testing in Python
    • Pytest Framework
    • Mocking in Python
    • 📝 Assignments
  • Python Best Practices
    • PEP 8 Style Guide
    • Docstrings in Python
    • Logging in Python
    • Code Optimization Tips
    • Debugging Techniques
    • 📝 Assignments
  • MySQL Database in Python
    • Introduction to MySQL with Python
    • DBMS vs File System
    • Connecting to MySQL Database
    • Create Database in MySQL
    • Create Table in MySQL
    • Insert Data in MySQL
    • Insert Multiple Rows
    • Select Data from MySQL
    • WHERE Clause in MySQL
    • Update Data in MySQL
    • Delete Data from MySQL
    • Parameterized Queries
    • Transaction Management
    • Error Handling
    • Connection Pooling
    • MySQL Drivers Guide
    • Joins in MySQL
    • Aggregation Functions
    • Backup MySQL Database
    • Best Practices
    • 📝 Assignments
  • MySQL Database Operations
    • SELECT Statement
    • MySQL Operators
    • DDL Statements
    • DML Statements
    • Subqueries
    • JOIN Operations
    • Aggregation
    • Case Study
    • 📝 Assignments
  • Graphics in Python
  • Threads in Python
    • Introduction to Threads
    • Process vs Threads
    • Concurrent Programming & GIL
    • Uses of Threads
    • Creating Threads
    • Single Tasking
    • Multi Tasking
    • Thread Synchronization
    • 📝 Assignments
  • Interview Questions & Answers
  • Python Case Studies
  • Multiple Choice Questions
  • 📝 Practice Problems
Get in Touch
  • tech2dsm@gmail.com

© Sankalan Data Tech

Python Language Interactive Tutorial

Python: Destructor

Python Destructor - Complete Guide

Learn about destructors in Python — the special methods that clean up objects when they're destroyed.

Created by Sankalan Data Tech Team Verified
Data Engineers, Analysts, Scientists & Trainers
Created by experienced Python developers, data engineers, and data scientists to make programming easy through practical examples, real-world experience, and clear explanations.
On this page:
  • What is a Destructor?
  • The __del__ Method
  • Garbage Collection in Python
  • When is __del__ Called?
  • Resource Cleanup
  • __del__ vs close()
  • Common Pitfalls
  • Best Practices
  • Try It Yourself
  • Quick Quiz
  • Frequently Asked Questions
Share this tutorial:
Twitter LinkedIn Facebook WhatsApp Reddit Telegram Email Copy Link
What You'll Learn Here
  • What is a destructor — the method that cleans up objects
  • The __del__ method — Python's destructor
  • Garbage collection — how Python manages memory
  • Resource cleanup — releasing files, connections, and more
  • __del__ vs close() — choosing the right approach
  • Best practices — writing clean destructors

What is a Destructor?

Just as a constructor is called when an object is created, a destructor is called when an object is destroyed. Its job is to clean up resources that the object was using — like closing files, releasing network connections, or freeing up memory.

Think of a destructor like the cleanup crew at the end of an event. The constructor sets everything up (like setting up tables and chairs), and the destructor takes everything down (like cleaning up after everyone leaves). It ensures that nothing is left behind that could cause problems.

In Python, the destructor is the __del__ method. It's called automatically when an object is about to be destroyed. However, unlike constructors, destructors are not as commonly used in Python because Python's garbage collector handles most memory management automatically.

💡 Key concept: A destructor is a special method that cleans up resources when an object is destroyed. It's the opposite of a constructor — while the constructor sets up the object, the destructor tears it down.

The __del__ Method

1

Understanding the __del__ Method

The __del__ method is Python's destructor. It's called automatically when an object is destroyed — either when the program ends, when you use the del keyword, or when the garbage collector removes the object.

Definition: The __del__ method is a special method in Python classes that is called when an object is about to be destroyed. It's used to clean up resources and perform any necessary cleanup operations.

# The __del__ method in action

class Resource:
    """A class that uses resources and needs cleanup"""
    
    def __init__(self, name):
        """Initialize the resource"""
        self.name = name
        print(f"Resource '{name}' created")
    
    def __del__(self):
        """Destructor - called when the object is destroyed"""
        print(f"Resource '{self.name}' destroyed and cleaned up")
    
    def use(self):
        """Use the resource"""
        print(f"Using resource '{self.name}'")

# Creating objects
print("Creating resources...")
r1 = Resource("File-1")
r2 = Resource("Database-1")

# Using resources
r1.use()
r2.use()

# The destructor will be called when:
# 1. The object goes out of scope
# 2. The program ends
# 3. We use the del keyword

print("\nDeleting r1...")
del r1  # This triggers __del__ for r1

print("\nProgram ending...")
# r2 will be destroyed when the program ends
# __del__ for r2 will be called automatically
                                

Key points about __del__:

  • Called automatically — when the object is destroyed
  • No parameters — only self is passed
  • No return — doesn't return anything
  • Not guaranteed — may not be called if the program crashes
  • Useful for cleanup — closing files, connections, etc.
  • Can cause issues — if not used carefully

What __del__ is used for:

  • File cleanup — closing open files
  • Network cleanup — closing connections
  • Database cleanup — closing database connections
  • Memory cleanup — freeing up resources
  • Logging — logging object destruction

Quick Check: What is the purpose of the __del__ method? (Answer: To clean up resources when an object is destroyed)

Garbage Collection in Python

2

How Python Manages Memory

Python uses a garbage collector to automatically manage memory. When objects are no longer needed, the garbage collector detects this and frees up the memory. The __del__ method is called as part of this process.

# Understanding garbage collection in Python

import gc
import time

class GarbageExample:
    """A class to demonstrate garbage collection"""
    
    def __init__(self, name):
        self.name = name
        print(f"Created: {name}")
    
    def __del__(self):
        print(f"Destroyed: {self.name}")

# 1. Objects are created
print("Creating objects...")
obj1 = GarbageExample("Object 1")
obj2 = GarbageExample("Object 2")
obj3 = GarbageExample("Object 3")

# 2. Objects can be manually deleted
print("\nDeleting obj1...")
del obj1  # __del__ is called immediately

# 3. Objects can be reassigned
print("\nReassigning obj2...")
obj2 = GarbageExample("Object 4")  # Old obj2 is destroyed

# 4. Objects can go out of scope
print("\nCreating objects in a function...")
def create_temp_object():
    temp = GarbageExample("Temporary")
    print("Function ending...")
    # temp is destroyed when the function ends

create_temp_object()

# 5. Garbage collector can be forced
print("\nForcing garbage collection...")
gc.collect()  # Forces garbage collection

# 6. Checking garbage collector statistics
print(f"\nGarbage collector stats: {gc.get_count()}")

# 7. Disabling garbage collector (not recommended)
# gc.disable()
# Enable it again
# gc.enable()
                                

Garbage collection key points:

  • Reference counting — objects are tracked by how many references point to them
  • Cyclic garbage collector — handles objects that reference each other
  • Automatic — Python handles memory management for you
  • gc module — provides tools to control garbage collection
  • Performance — garbage collection happens automatically when needed

Quick Check: How does Python manage memory? (Answer: Using automatic garbage collection)

When is __del__ Called?

3

Understanding When Destructors Run

The __del__ method is called in several situations. Understanding when it's called helps you write better destructors and avoid unexpected behavior.

# When is __del__ called?

class Demo:
    """A class to demonstrate when __del__ is called"""
    
    def __init__(self, name):
        self.name = name
        print(f"{self.name}: Created")
    
    def __del__(self):
        print(f"{self.name}: Destroyed")

# 1. When an object is explicitly deleted
print("1. Explicit deletion:")
d1 = Demo("Object 1")
del d1  # __del__ called immediately

# 2. When a variable is reassigned
print("\n2. Reassignment:")
d2 = Demo("Object 2")
d2 = Demo("Object 3")  # Old Object 2 is destroyed

# 3. When an object goes out of scope
print("\n3. Out of scope:")
def create_object():
    d3 = Demo("Object 4")
    # d3 goes out of scope when function ends
create_object()

# 4. When the program ends
print("\n4. Program ending:")
d4 = Demo("Object 5")
# d4 will be destroyed when the program ends

# 5. With multiple references
print("\n5. Multiple references:")
d5 = Demo("Object 6")
d6 = d5  # Both d5 and d6 refer to the same object
d5 = None  # Object still exists because d6 references it
del d6  # Now the object is destroyed

# 6. Circular references
print("\n6. Circular references:")
class Circular:
    def __init__(self, name):
        self.name = name
        self.ref = None
    
    def __del__(self):
        print(f"{self.name}: Destroyed")

a = Circular("A")
b = Circular("B")
a.ref = b
b.ref = a
# a and b reference each other, so they won't be destroyed immediately
# The cyclic garbage collector will handle them
                                

When __del__ is called:

  • Explicit deletion — using the del keyword
  • Reassignment — when the variable is assigned to something else
  • Out of scope — when the object goes out of scope
  • Program end — when the program finishes
  • Garbage collection — when the garbage collector runs

Quick Check: When is __del__ called? (Answer: When the object is destroyed, either by del, reassignment, or garbage collection)

Resource Cleanup

4

Using Destructors for Cleanup

The most common use of destructors is to clean up resources. This includes closing files, closing database connections, releasing network connections, and freeing up other system resources.

# Using destructors for resource cleanup

class FileHandler:
    """A class that handles file operations with cleanup"""
    
    def __init__(self, filename, mode='r'):
        self.filename = filename
        self.mode = mode
        self.file = None
        print(f"Opening file: {filename}")
        try:
            self.file = open(filename, mode)
        except Exception as e:
            print(f"Error opening file: {e}")
    
    def read(self):
        """Read content from the file"""
        if self.file:
            return self.file.read()
        return None
    
    def write(self, content):
        """Write content to the file"""
        if self.file and 'w' in self.mode:
            self.file.write(content)
    
    def __del__(self):
        """Destructor - close the file if it's open"""
        if self.file:
            print(f"Closing file: {self.filename}")
            self.file.close()
            self.file = None

# Using the FileHandler
print("Creating a file handler...")
fh = FileHandler("test.txt", "w")
fh.write("Hello, World!")
# The file is still open

print("Using the file handler...")
# The destructor will close the file when the object is destroyed

print("Deleting the file handler...")
del fh  # __del__ is called, closing the file

# Another example: Database connection
class DatabaseConnection:
    """A class that manages a database connection"""
    
    def __init__(self, connection_string):
        self.connection_string = connection_string
        self.connection = None
        print(f"Connecting to database: {connection_string}")
        # In a real scenario, you'd actually connect here
        self.connection = "Connected"
    
    def query(self, sql):
        """Execute a query"""
        if self.connection:
            print(f"Executing: {sql}")
            return "Results"
        return None
    
    def __del__(self):
        """Destructor - close the connection"""
        if self.connection:
            print(f"Closing database connection: {self.connection_string}")
            self.connection = None

# Using the DatabaseConnection
print("\nCreating a database connection...")
db = DatabaseConnection("localhost:3306/mydb")
db.query("SELECT * FROM users")
# The connection is still open

print("Deleting the database connection...")
del db  # __del__ is called, closing the connection
                                

Resources that benefit from cleanup:

  • Files — close open files
  • Database connections — close connections
  • Network connections — close sockets
  • Graphics resources — free up GPU memory
  • Temporary files — delete temporary files

Quick Check: What is the main use of destructors? (Answer: Cleaning up resources like files and connections)

__del__ vs close()

5

Choosing the Right Approach

While destructors are useful, they're not always the best way to clean up resources. Sometimes it's better to use explicit close() methods or context managers. Here's why and when to use each.

# __del__ vs close() - A comparison

class ResourceWithDel:
    """Using __del__ for cleanup"""
    
    def __init__(self, name):
        self.name = name
        self.is_open = True
        print(f"Resource '{name}' opened")
    
    def __del__(self):
        if self.is_open:
            print(f"__del__: Closing resource '{self.name}'")
            self.is_open = False
    
    def use(self):
        if self.is_open:
            print(f"Using resource '{self.name}'")

class ResourceWithClose:
    """Using close() method for cleanup"""
    
    def __init__(self, name):
        self.name = name
        self.is_open = True
        print(f"Resource '{name}' opened")
    
    def close(self):
        if self.is_open:
            print(f"close(): Closing resource '{self.name}'")
            self.is_open = False
    
    def use(self):
        if self.is_open:
            print(f"Using resource '{self.name}'")
    
    def __del__(self):
        # Still include __del__ as a backup
        if self.is_open:
            print(f"__del__ (backup): Closing resource '{self.name}'")
            self.is_open = False

# Using ResourceWithDel
print("=== Using __del__ ===")
r1 = ResourceWithDel("File-1")
r1.use()
del r1  # Cleanup happens here

# Using ResourceWithClose
print("\n=== Using close() ===")
r2 = ResourceWithClose("File-2")
r2.use()
r2.close()  # Explicit cleanup

# Using context manager (the modern way)
print("\n=== Using context manager ===")
class ResourceContext:
    def __init__(self, name):
        self.name = name
        print(f"Resource '{name}' opened")
    
    def __enter__(self):
        return self
    
    def __exit__(self, exc_type, exc_val, exc_tb):
        print(f"Context manager: Closing resource '{self.name}'")
    
    def use(self):
        print(f"Using resource '{self.name}'")

with ResourceContext("File-3") as r3:
    r3.use()
# Automatic cleanup when the block ends

# Recommendations:
# 1. Use context managers (with statement) for resource management
# 2. Use explicit close() methods when context managers aren't available
# 3. Use __del__ as a backup, but don't rely on it exclusively
                                

Comparison of approaches:

  • __del__ — automatic, but not guaranteed and can be problematic
  • close() — explicit, reliable, but requires manual calling
  • Context managers — best of both worlds, automatic and reliable
  • Best practice — use context managers when possible

Quick Check: What is the recommended way to manage resources? (Answer: Using context managers with the 'with' statement)

Common Pitfalls

6

Things to Watch Out For

Destructors can be tricky. Here are some common issues you might encounter and how to avoid them.

# Common pitfalls with destructors

# Pitfall 1: Relying on __del__ for important cleanup
class RiskyResource:
    def __init__(self, name):
        self.name = name
        print(f"Resource '{name}' created")
    
    def __del__(self):
        print(f"Resource '{self.name}' cleaned up")
        # If the program crashes, __del__ may not be called

# Pitfall 2: Circular references
class Node:
    def __init__(self, value):
        self.value = value
        self.ref = None
    
    def __del__(self):
        print(f"Node {self.value} destroyed")

print("\n=== Circular References ===")
a = Node(1)
b = Node(2)
a.ref = b
b.ref = a  # Circular reference
del a
del b
# gc.collect() will handle this

# Pitfall 3: Accessing attributes that may not exist
class FragileDestructor:
    def __init__(self, name):
        self.name = name
    
    def __del__(self):
        # This could fail if __init__ didn't run completely
        print(f"Destroying {self.name}")  # Works fine

# But this could fail:
class BrokenDestructor:
    def __init__(self, name):
        # If an exception happens here, name may not be set
        self.name = name
    
    def __del__(self):
        # Accessing name might cause an error if __init__ failed
        print(f"Destroying {self.name}")  # Safe

# Pitfall 4: Overriding __del__ incorrectly
class WrongDel:
    def __del__(self):
        print("Cleaning up")
        # Don't call super().__del__() unless you need to

# Pitfall 5: Creating new objects in __del__
class CreatesInDel:
    def __del__(self):
        # Don't create new objects in __del__
        # This can cause issues with garbage collection
        print("Creating new object")  # Not recommended

# Best practice: Use context managers instead
class SafeResource:
    def __init__(self, name):
        self.name = name
    
    def __enter__(self):
        return self
    
    def __exit__(self, exc_type, exc_val, exc_tb):
        print(f"Cleaning up {self.name}")
    
    def use(self):
        print(f"Using {self.name}")

# This is the safe way
with SafeResource("Safe") as resource:
    resource.use()
                                

Common pitfalls:

  • Unreliable cleanup — __del__ may not be called
  • Circular references — can prevent objects from being destroyed
  • Missing attributes — __init__ may not have run
  • Creating objects in __del__ — can cause issues
  • Performance impact — heavy operations in __del__

Quick Check: What is a common pitfall with destructors? (Answer: Relying on __del__ for important cleanup that may not run)

Best Practices for Destructors

7

Writing Professional Destructors

# Best practices for destructors

import gc
import weakref

# 1. Use context managers instead of __del__ when possible
class GoodResource:
    """A resource that uses context management"""
    
    def __init__(self, name):
        self.name = name
        print(f"Opening {name}")
    
    def __enter__(self):
        return self
    
    def __exit__(self, exc_type, exc_val, exc_tb):
        print(f"Closing {self.name}")
    
    def use(self):
        print(f"Using {self.name}")

# 2. If you must use __del__, keep it simple
class SimpleDestructor:
    def __init__(self, name):
        self.name = name
        self._closed = False
    
    def close(self):
        if not self._closed:
            print(f"Closing {self.name}")
            self._closed = True
    
    def __del__(self):
        # Only as a backup
        self.close()

# 3. Use weak references to avoid circular references
class Parent:
    def __init__(self, name):
        self.name = name
        self.children = []
    
    def add_child(self, child):
        self.children.append(weakref.ref(child))

class Child:
    def __init__(self, name):
        self.name = name
        self.parent = None
    
    def set_parent(self, parent):
        self.parent = weakref.ref(parent)

# 4. Don't rely on __del__ for critical cleanup
class ResourceWithBackup:
    def __init__(self, filename):
        self.filename = filename
        self.file = None
    
    def open_file(self):
        self.file = open(self.filename, 'w')
    
    def close_file(self):
        if self.file:
            self.file.close()
            self.file = None
    
    def __del__(self):
        self.close_file()  # Backup cleanup

# 5. Use try-finally for guaranteed cleanup
def use_resource_safely():
    resource = None
    try:
        resource = GoodResource("Safe")
        resource.use()
    finally:
        if resource:
            resource.close()

# 6. Consider using the 'atexit' module for program-end cleanup
import atexit

class GlobalResource:
    def __init__(self, name):
        self.name = name
        print(f"Creating {name}")
        atexit.register(self.cleanup)
    
    def cleanup(self):
        print(f"Cleaning up {self.name}")

# 7. Document your destructor behavior
class DocumentedDestructor:
    """
    A class with a documented destructor.
    
    The __del__ method closes any open resources.
    However, for guaranteed cleanup, use the close() method
    or the context manager interface.
    """
    
    def __del__(self):
        """Close resources when the object is destroyed."""
        pass
                                

Best practices summary:

  • Use context managers — the preferred way to manage resources
  • Keep __del__ simple — avoid complex operations
  • Avoid circular references — use weak references
  • Don't rely on __del__ — use explicit cleanup methods
  • Document behavior — explain what the destructor does

Quick Check: What is the best way to manage resources in Python? (Answer: Using context managers with the 'with' statement)

Try It Yourself

Experiment with destructors in the editor below.

Loading Pyodide... 0%
Python Code Editor
========================================
DESTRUCTOR PRACTICE
========================================

1. BASIC DESTRUCTOR
Created: Object 1
Created: Object 2
Destroyed: Object 1

2. RESOURCE CLEANUP
Opening: data.txt
Writing: Hello, World!
Closing: data.txt

3. CONTEXT MANAGER
Entering: Resource 1
Using: Resource 1
Exiting: Resource 1

4. MULTIPLE OBJECTS
Created: Object 1
Created: Object 2
Created: Object 3
Clearing list...
Destroyed: Object 1
Destroyed: Object 2
Destroyed: Object 3

Destructor practice complete!
🏆

You've Got It!

You now understand destructors in Python. You know about __del__, garbage collection, and how to clean up resources properly.

Quick Quiz

Test what you've learned:

1. What is the purpose of the __del__ method?
2. When is __del__ called?
3. What is the recommended way to manage resources?
4. What is a common pitfall with destructors?
5. What is the difference between __del__ and close()?

Frequently Asked Questions

What is the difference between __init__ and __del__? ▼

__init__ is the constructor that's called when an object is created. It initializes the object's attributes. __del__ is the destructor that's called when an object is destroyed. It cleans up resources. __init__ sets things up; __del__ tears them down.

Can I rely on __del__ for critical cleanup? ▼

No, you should not rely on __del__ for critical cleanup. It may not be called if the program crashes or if the interpreter exits abnormally. Use context managers or explicit close() methods for critical cleanup.

What is garbage collection in Python? ▼

Garbage collection is the automatic process of freeing memory when objects are no longer needed. Python uses reference counting and a cyclic garbage collector to manage memory. It automatically detects and removes objects that are no longer referenced.

What's a common interview question about destructors? ▼

Common questions include: "What is the purpose of __del__?" "What is the difference between __init__ and __del__?" "How does garbage collection work in Python?" and "What are the pitfalls of using destructors?"

Should I always define __del__ for my classes? ▼

No, you should only define __del__ when you need to clean up resources. For most classes, it's not necessary and can actually cause problems. If you're not managing external resources, you don't need a destructor.

What is the difference between del and __del__? ▼

del is a keyword that deletes a reference to an object. When the last reference is deleted, the object is destroyed and __del__ is called. __del__ is the method that's called when the object is actually destroyed. del triggers the destruction; __del__ handles the cleanup.

Where to Go From Here

Now that you understand destructors, check out these related topics:

Built Class Methods and Attributes

Learn about special methods and attributes in Python classes.

Learn More →

Class and Instance Variables

Learn the difference between class and instance variables.

Learn More →

Inheritance

Learn how to create class hierarchies with inheritance.

Learn More →
Interview Resources
  • Python Syntax & Variables Interview Questions
  • Top SQL Interview Questions & Answers
  • SQL Joins: Displaying Data from Multiple Tables FAQ
  • Python Lists and Dictionaries Interview Questions
  • Python OOP Interview Questions
  • SQL Set Operators Interview Questions
Previous: Constructors Next: Built Class Methods and Attributes →