Concepts / The Constructor: Initializing Objects with __init__

The Constructor: Initializing Objects with __init__

Objects have a complete lifecycle: creation (via __init__), active use, and destruction (via __del__). Python calls these special methods automatically.

  • Programming

A Complete Object Lifecycle

An object is not just a value that appears and disappears. It passes through a lifecycle: Python creates it, initializes it, lets your program use it, and eventually destroys it. The special method __init__ participates at the beginning of that lifecycle. If a class defines __del__, that method participates at the end.

When you create an instance, Python allocates memory for the object and calls its __init__ method automatically. The method gives the class a place to establish sensible starting values. After initialization, the object can be used through its methods and attributes. Later, when the object is no longer needed, Python destroys it and calls __del__ if the class defines that method.

Python callsready for useno longer neededObject createdmemory allocated__init__initial values setActive objectmethods and attributesavailableObject destroyed__del__ may run
What happens to an object from creation through initialization and use until Python destroys it?

Creation Before Use

A class defines the behavior and structure from which instances are created. An instance is one individual object made from that class. When an instance is created, Python automatically calls __init__. You do not normally call __init__ yourself to begin the object's lifecycle.

instantiatePython callssets initial stateClass definitionmethods and initializationrulesNew instanceobject created__init__self receives the instanceReady instanceattributes available
What is the execution order from a class definition to an initialized object?
python

In this example, User is the class and user is an instance. When User("Mina") creates the instance, Python calls __init__ automatically. The self parameter identifies that particular instance. The assignments create instance attributes named name and active, so this instance begins with name set to "Mina" and active set to True.

Building Initial State

The main job of __init__ is to make an instance ready for predictable use. An instance attribute is data attached to one particular object. Writing self.name = name attaches the value from the parameter name to the current object identified by self. Because each instance receives its own call to __init__, each instance has its own separate set of initialized attributes.

__init__New objectbefore initializationProfile instancename and active initialized
How does __init__ transform a newly created object into an object with initialized instance attributes?
ownsownsstoresselfcurrent instancenameinstance attribute"Mina"assigned valueactiveinstance attribute
How does self identify the current object, and where do assignments such as self.name = name attach their data?

Initialize every attribute that the object will use inside __init__. This helps every instance begin in a valid and predictable state instead of requiring later code to guess whether an attribute exists.

createscreatesUserclass definitionuser_aname: Minauser_bname: Omar
How do multiple individual instances relate to one shared class definition?

Destruction Triggers

What do you think happens?

A variable holds an object. The variable is then reassigned to 42. What lifecycle event should you expect for the original object?

  • Its __init__ method runs again
  • Its __del__ method may be called as the object is destroyed
  • Nothing can happen until a new object is created
  • The original object becomes a class
Reveal answer

Answer: Its __del__ method may be called as the object is destroyed.

Variable reassignment can make the original object no longer needed. At that destruction moment, Python calls __del__ if the class defines it.

The destructor __del__ is called when an object is about to be destroyed. The source identifies three common triggers: a variable holding the object is reassigned, a variable goes out of scope, or the program terminates. In each case, Python decides that the object is no longer needed and gives __del__ a final opportunity to perform cleanup.

one possible triggerone possible triggerone possible triggerobject destroyedobject destroyedobject destroyedObjectcurrently in useVariable reassignedold object no longer neededVariable leaves scopelocal variable ceases toexistProgram terminatesremaining objects aredestroyed__del__final cleanup opportunity
What changes when a variable is reassigned, a local variable leaves scope, or the program terminates?
python
Output
created first
destroyed first

The first assignment creates a Marker instance, so __init__ runs and stores the label. The second assignment replaces the object held by marker with the value 42. The original Marker object is then no longer needed in this simple sequence, so Python destroys it and calls __del__.

Cleanup Responsibilities

Most Python objects do not need a destructor. Python's garbage collector handles memory automatically 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.

python

This example illustrates the intended division of responsibility: __init__ prepares the object and any resources it needs, while __del__ provides a final chance to release resources before the object vanishes. You cannot stop the object from being destroyed. You can only use __del__ for cleanup at that final moment.

Mistakes with Initialization and Destruction

  • Treating __init__ as a normal method that must be called manually.

    Python already calls __init__ when the instance is created. Calling it again repeats initialization and is not needed for ordinary object creation.

    Fix: Create the instance and let Python invoke __init__ automatically.

  • Assigning to a local name instead of an instance attribute.

    This does not attach the value to the object. The instance needs an assignment using self, such as self.name = name.

    Fix: Use self.attribute_name when storing data on the current instance.

  • Assuming all instances share one set of instance attributes.

    Each instance receives its own call to __init__ and its own separate set of attributes.

    Fix: Think of the class as the shared definition and each instance as an individual object with independently initialized attributes.

  • Adding __del__ to every class without managing an external resource.

    Most objects do not need explicit cleanup because Python automatically manages memory.

    Fix: Use __del__ when the object manages an external resource such as a file handle, database connection, or network socket.

Trace the Lifecycle

MEDIUM

Write a class named Counter with an __init__ method that stores a starting number in an instance attribute named value. Then add a __del__ method that announces the value during cleanup. Create one Counter instance, use a second variable to refer to it, and reassign the first variable. Trace which event happens at creation and which event happens when the original object is no longer needed.

Hints
  • The first parameter of both special methods should identify the current instance.
  • Store the constructor's starting number with an assignment that begins with self.
  • Reassignment matters only when the original object is no longer held by the relevant variables.

Following Two Instances

A class creates two objects, first and second. Each object initializes its own label. The variable first is then reassigned. Which object is affected by that reassignment?

Create first: Python creates the first instance and calls __init__, so the instance receives its own initialized label.

Create second: Python creates a separate second instance and calls __init__ again. This instance receives an independent set of attributes.

Reassign first: The name first no longer refers to the original first object. That original object may be destroyed if no relevant variable still holds it.

Keep tracing second: Reassigning first does not change the attributes belonging to second. It is a separate instance.

Each object was initialized separately. Reassigning first can trigger destruction of the original first object, while the second object remains active.

Key Takeaways

  1. __init__ runs automatically when Python creates an instance.
  2. The self parameter identifies the particular instance being initialized.
  3. Assignments such as self.name = name create or set instance attributes.
  4. Each instance has its own separately initialized attributes.
  5. __del__ runs when an object is about to be destroyed, including after reassignment, when a variable leaves scope, or when the program ends.
  6. Most objects do not need __del__; it is mainly useful for final cleanup of external resources.

Key Takeaways

  • __init__ is automatically called during object instantiation to establish the object's initial state.
  • self refers to the current instance, and self.attribute assignments store data on that instance.
  • Every instance receives its own initialization and its own separate instance attributes.
  • __del__ is called when Python is about to destroy an object, including after variable reassignment, scope exit, or program termination.
  • Destructors are uncommon because Python manages memory automatically; they are mainly useful for cleanup involving external resources.