Why is __init__ always called after __new__?
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
In Python, __new__ and __init__ are the two steps of object creation. __new__ allocates memory and returns a new instance, then __init__ initializes that instance with attributes. __init__ is always called after __new__ because Python's type machinery calls them in sequence: first create the object, then initialize it. Understanding this distinction matters when implementing singletons, immutable types, caching, and metaclasses.
The Two-Step Process
When you write MyClass(args), Python executes:
__new__ is responsible for creating and returning the instance. __init__ is responsible for setting up the instance's attributes. Python only calls __init__ if __new__ returns an instance of the class.
new — The Constructor
__new__ is a static method (it takes cls, the class itself, not an instance). It must return an instance — usually by calling super().__new__(cls).
init — The Initializer
__init__ receives the already-created instance as self and sets up its attributes. It must return None — if it returns anything else, Python raises TypeError.
Why new Exists: Immutable Types
Immutable types like int, str, tuple, and frozenset cannot be modified after creation. Since __init__ runs after the object exists, it is too late to change an immutable object. __new__ lets you customize the object during creation:
Singleton Pattern with new
Note that __init__ runs every time you call Singleton(), even if __new__ returns an existing instance. To prevent re-initialization, add a guard:
new Returning a Different Type
If __new__ returns an instance of a different class, __init__ is NOT called:
Python checks: is the return value of __new__ an instance of cls? If not, __init__ is skipped.
Object Caching with new
The Full Object Creation Chain
The metaclass __call__ method orchestrates the __new__ → __init__ sequence.
Common Pitfalls
- Forgetting to call
super().__new__(cls): If__new__does not callsuper().__new__(cls), no instance is created and you getNoneor an error. Always delegate to the parent class's__new__. - Returning a non-instance from
__new__accidentally: If__new__returns the wrong type,__init__is silently skipped. This is rarely intended and causes confusing bugs. - Re-initialization in Singleton pattern:
__init__runs every time the class is called, even when__new__returns a cached instance. Add an_initializedflag to prevent overwriting attributes. - Trying to modify immutable types in
__init__: You cannot change the value ofint,str, ortuplein__init__because the object is already created. Override__new__to customize immutable types. - Using
__new__when__init__suffices: Most classes should only implement__init__. Use__new__only for immutable types, singletons, caching, or metaclass customization. Unnecessary__new__overrides add complexity.
Summary
__new__creates and returns a new instance;__init__initializes it with attributes- Python calls
__new__first, then__init__only if__new__returned an instance of the class - Override
__new__for immutable types (int, str, tuple), singletons, and object caching - Override
__init__for setting up mutable instance attributes (the common case) - In the Singleton pattern, guard
__init__with a flag to prevent re-initialization

