Concepts / The Destructor: Cleaning Up with __del__

The Destructor: Cleaning Up with __del__

The exact moment of destruction depends on when Python decides the object is no longer needed.

  • Programming

An Object’s Lifecycle

A Python object has a lifecycle with three broad stages: creation, active use, and destruction. During creation, Python calls __init__ so the object can receive its initial attributes and prepare any resources it needs. During active use, your program accesses the object and calls its methods. When the object is no longer needed, Python destroys it and calls __del__ if the class defines that method.

Object creationclass call__init__initial stateActive usemethods and attributesObject destructionobject no longer needed__del__final cleanupautomatically callsproduces initialized objectobject is no longer neededif defined
What happens to an object from the moment it is created, through initialization and use, until it is destroyed?

Initialization with __init__

__init__ is a special method that runs automatically when a new instance of a class is created. It is used to give the object a sensible starting state. Assignments such as self.name = name attach attributes to the particular object being created.

Device()create instance__init__runs automaticallyselfcurrent instanceInstance attributesname and statusInitialized objectready for useinvokesreceivesassignsestablish
What is the execution flow from calling a class to running __init__ and producing an initialized object?
python

When the final line creates a Device instance, Python automatically runs __init__. The self parameter refers to that particular Device object. The assignments create its name and status attributes, so the object begins in a predictable state rather than requiring later code to add those attributes before use.

Device instanceno initialized attributesDevice instancename: Sensorstatus: readyassigned by __init____init__ assignscontains
How do the values assigned in __init__ become instance attributes that define the object's initial state?

Classes and Independent Instances

A class defines the structure and behavior that its instances receive. Each instance has its own separate set of attributes. Therefore, one call to __init__ initializes one specific object through self; another object created from the same class receives its own independent initialization.

Device class__init__ behaviordevice_onename: Sensordevice_twoname: Cameracreatescreates
What does a class define, and how do multiple instances contain their own initialized attributes?
python

The two Counter instances are initialized separately. first receives its own value attribute with a starting value of 1, while second receives its own value attribute with a starting value of 10. The class supplies the initialization rule, but each object receives its own attribute set.

Destruction with __del__

__del__ is a destructor method. Python invokes it when an object is about to be destroyed, giving the object a final opportunity to perform cleanup. The object cannot be kept alive by __del__; the method is a last moment for cleanup before the object vanishes.

Code walkthrough
class Session:
    def __init__(self, name):
        self.name = name
        print("created", self.name)

    def __del__(self):
        print("cleaning up", self.name)

session = Session("A")
session = "finished"
  1. 1
    Python creates a Session object for the call Session("A").
  2. 2
    Python automatically runs __init__ for that object.
  3. 3
    The object remains available through the variable session.
  4. 4
    The variable is reassigned to the string "finished".
  5. 5
    The original Session object is no longer needed through that variable, so Python destroys it and calls __del__ if it is ready to be destroyed.
  • The class defines both lifecycle methods.
  • The constructor stores the name and announces creation.
  • The destructor announces final cleanup.
  • The first assignment creates a Session instance and runs __init__.
  • Reassignment makes the original Session object no longer held by session.
Session objectsession = Session("A")sessionholds Session"finished"new variable value__del__final cleanupheld byreassigned toobject becomes no longer needed
How does reassigning a variable cause an object's __del__ method to be called?

Cleanup Responsibilities

Most Python objects do not need __del__. Python's garbage collector automatically reclaims memory when objects are no longer in use. A destructor becomes useful when an object manages an external resource, such as an open file handle, a database connection, or a network socket. In those cases, __del__ can perform a final cleanup action before the object is destroyed.

python

This example shows the lifecycle pattern: __init__ prepares the object and records the resource-related state, while __del__ provides a final place for cleanup. The source examples identify files, database connections, and network sockets as resources that may need explicit release. A simple object that only contains ordinary Python attributes generally has no special cleanup task for __del__.

Common Lifecycle Mistakes

  • Common mistake

    Treating __init__ as an ordinary method that must be called manually.

    What it looks like
    device = Device("Sensor")
    Why it fails

    __init__ runs automatically when the instance is created.

    Do this instead

    Define __init__ for initialization and let the class call it during instantiation.

  • Common mistake

    Forgetting self when assigning an instance attribute.

    What it looks like
    name = name
    Why it fails

    The assignment does not attach the value to the specific object through self.

    Do this instead

    Use self.name = name when the value belongs to the instance.

  • Common mistake

    Initializing some attributes only later during normal use.

    What it looks like

    An object is created without setting an attribute that its methods expect.

    Why it fails

    Instances may begin in different or invalid states.

    Do this instead

    Initialize every attribute the object will use in __init__.

  • Common mistake

    Assuming __del__ is needed for every class.

    What it looks like

    Adding a destructor to a class that only stores ordinary attributes.

    Why it fails

    Python automatically reclaims memory for objects that are no longer in use.

    Do this instead

    Use __del__ only when the object has a cleanup responsibility such as an external resource.

  • Common mistake

    Assuming reassignment merely changes a variable and has no lifecycle effect.

    What it looks like
    session = "finished" after session held a Session object.
    Why it fails

    The original object may become no longer needed, which can trigger destruction and __del__.

    Do this instead

    When tracing code, track both the variable's new value and the old object's remaining lifecycle.

Trace the Lifecycle

What do you think happens?

A class defines both __init__ and __del__. A variable first receives an instance and is then reassigned to another value. Which lifecycle events should you trace?

  • Only __init__

  • Only __del__

  • __init__ for creation, then possible __del__ for the original object

  • Neither method

Reveal answer
Answer:

__init__ for creation, then possible __del__ for the original object

Creating the instance automatically runs __init__. Reassigning the variable can make the original object no longer needed, which is one of the situations in which Python destroys the object and calls __del__ if it is defined.

MEDIUM

Trace this class on paper. Identify which attributes are created by __init__, which object each self refers to, and what event can lead to __del__ for the first object.

class Ticket:
    def __init__(self, number):
        self.number = number
    def __del__(self):
        print("cleaning", self.number)
ticket = Ticket(1)
ticket = Ticket(2)
Hints
  • There are two separate calls to the class.
  • Each call runs __init__ for its own instance.
  • The variable is reassigned after the first instance is created.
  • Track the first Ticket object separately from the second Ticket object.

Key Takeaways

  1. 1
    __init__ runs automatically when a new instance is created.
  2. 2
    self identifies the specific instance whose attributes are being initialized.
  3. 3
    Every instance has its own separate attributes and receives its own call to __init__.
  4. 4
    __del__ runs when an object is about to be destroyed, including situations involving reassignment, scope ending, or program termination.
  5. 5
    Most objects do not need __del__; it is mainly useful when an object manages an external resource that needs cleanup.

At a glance

  • __init__ establishes an object's initial state during instantiation.
  • self allows initialization to target the current instance.
  • Objects move from creation through active use to destruction.
  • __del__ provides a final cleanup opportunity when Python destroys an object.
  • Use destructors selectively, especially for objects that manage external resources.

Related concepts

More concepts starting with T