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
Interactive lab

Try it: Classes, Instances and Attributes

How a class creates instances with __init__ and self, why an attribute read checks the instance's __dict__ before the class, why assigning through an instance never changes the class, how a class-level list is shared by every instance, and why obj.method(x) is Class.method(obj, x).

How it works

  1. Dog(...) makes a new, empty instance and calls Dog.__init__(new_object, ...); self.name = ... stores into that object's __dict__.
  2. Reading obj.attr looks in obj.__dict__ first, then in the class.
  3. Assigning obj.attr = value always writes obj.__dict__, so it shadows a class attribute for that one object only.
  4. Mutating a class-level list (self.tricks.append) changes the one list every instance shares.
  5. obj.method is found on the class and bound to obj, so obj.method(x) runs Class.method(obj, x).

Default run (30 steps): Ready: class Dog and the statements you picked. Watch where each attribute is found and where each assignment writes. … Finished. Printed: ['sit'] / Wolf / Canis familiaris / Fido is 5.

Simplified: The lab's own small Python interpreter runs a fixed, hand-written script (you choose the variant and the values, never the code); nothing is executed as real Python. Every script was run in CPython 3.12 with the same inputs and the lab reproduces its output and error messages. Object numbers are illustrative, not real id() values.

Educational simulation

Loading the simulation…

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.

Object createdmemory allocated__init__initial values setActive objectmethods and attributesavailableObject destroyed__del__ may runPython callsready for useno longer needed
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.

Class definitionmethods and initializationrulesNew instanceobject created__init__self receives the instanceReady instanceattributes availableinstantiatePython callssets initial state
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.

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

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.

Userclass definitionuser_aname: Minauser_bname: Omarcreatescreates
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.

Objectcurrently in useVariable reassignedold object no longer neededVariable leaves scopelocal variable ceases toexistProgram terminatesremaining objects aredestroyed__del__final cleanup opportunityone possible triggerone possible triggerone possible triggerobject destroyedobject destroyedobject destroyed
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

  • Common mistake

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

    What it looks like
    user = User("Mina")
    user.__init__("Mina")
    Why it fails

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

    Do this instead

    Create the instance and let Python invoke __init__ automatically.

  • Common mistake

    Assigning to a local name instead of an instance attribute.

    What it looks like
    def __init__(self, name):
        name = name
    Why it fails

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

    Do this instead

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

  • Common mistake

    Assuming all instances share one set of instance attributes.

    What it looks like
    first = User("Mina")
    second = User("Omar")
    Why it fails

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

    Do this instead

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

  • Common mistake

    Adding __del__ to every class without managing an external resource.

    Why it fails

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

    Do this instead

    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.
Worked example

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?

  1. 1
    Create first

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

  2. 2
    Create second

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

  3. 3
    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.

  4. 4
    Keep tracing second

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

Result

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

Key Takeaways

  1. 1
    __init__ runs automatically when Python creates an instance.
  2. 2
    The self parameter identifies the particular instance being initialized.
  3. 3
    Assignments such as self.name = name create or set instance attributes.
  4. 4
    Each instance has its own separately initialized attributes.
  5. 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. 6
    Most objects do not need __del__; it is mainly useful for final cleanup of external resources.

At a glance

  • __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.

Related concepts

More concepts starting with T