Python
Object-Oriented Programming
__init__
__new__
Method Order

Why is __init__ always called after __new__?

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

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:

python
1# What Python does internally:
2obj = MyClass.__new__(MyClass, args)  # Step 1: Create instance
3if isinstance(obj, MyClass):
4    obj.__init__(args)                 # Step 2: Initialize instance

__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

python
1class MyClass:
2    def __new__(cls, *args, **kwargs):
3        print(f"__new__ called with cls={cls.__name__}")
4        instance = super().__new__(cls)  # Allocate memory
5        return instance
6
7    def __init__(self, value):
8        print(f"__init__ called with value={value}")
9        self.value = value
10
11obj = MyClass(42)
12# Output:
13# __new__ called with cls=MyClass
14# __init__ called with value=42

__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

python
1class Person:
2    def __init__(self, name, age):
3        self.name = name
4        self.age = age
5
6p = Person("Alice", 30)
7print(p.name)  # "Alice"
8print(p.age)   # 30

__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:

python
1class PositiveInt(int):
2    def __new__(cls, value):
3        if value < 0:
4            value = abs(value)
5        return super().__new__(cls, value)
6
7    # __init__ cannot modify an int — it's immutable
8    # def __init__(self, value):
9    #     self = abs(value)  # This does NOT work
10
11print(PositiveInt(-5))   # 5
12print(PositiveInt(3))    # 3
13print(type(PositiveInt(3)))  # <class 'PositiveInt'>

Singleton Pattern with new

python
1class Singleton:
2    _instance = None
3
4    def __new__(cls, *args, **kwargs):
5        if cls._instance is None:
6            cls._instance = super().__new__(cls)
7        return cls._instance
8
9    def __init__(self, value=None):
10        # __init__ is called every time Singleton() is called
11        if value is not None:
12            self.value = value
13
14a = Singleton(10)
15b = Singleton(20)
16
17print(a is b)      # True — same instance
18print(a.value)     # 20 — __init__ ran again and overwrote value

Note that __init__ runs every time you call Singleton(), even if __new__ returns an existing instance. To prevent re-initialization, add a guard:

python
1class Singleton:
2    _instance = None
3    _initialized = False
4
5    def __new__(cls, *args, **kwargs):
6        if cls._instance is None:
7            cls._instance = super().__new__(cls)
8        return cls._instance
9
10    def __init__(self, value=None):
11        if not self._initialized:
12            self.value = value
13            self._initialized = True
14
15a = Singleton(10)
16b = Singleton(20)
17print(a.value)  # 10 — not overwritten

new Returning a Different Type

If __new__ returns an instance of a different class, __init__ is NOT called:

python
1class MyClass:
2    def __new__(cls):
3        print("__new__ called")
4        return 42  # Returning an int, not a MyClass instance
5
6    def __init__(self):
7        print("__init__ called")  # Never called!
8
9obj = MyClass()
10print(obj)        # 42
11print(type(obj))  # <class 'int'>
12# Only "__new__ called" is printed — __init__ is skipped

Python checks: is the return value of __new__ an instance of cls? If not, __init__ is skipped.

Object Caching with new

python
1class CachedString(str):
2    _cache = {}
3
4    def __new__(cls, value):
5        if value in cls._cache:
6            return cls._cache[value]
7        instance = super().__new__(cls, value)
8        cls._cache[value] = instance
9        return instance
10
11a = CachedString("hello")
12b = CachedString("hello")
13c = CachedString("world")
14
15print(a is b)  # True — same cached instance
16print(a is c)  # False — different string

The Full Object Creation Chain

python
1class Meta(type):
2    def __call__(cls, *args, **kwargs):
3        print(f"1. Meta.__call__ for {cls.__name__}")
4        instance = cls.__new__(cls, *args, **kwargs)
5        print(f"2. {cls.__name__}.__new__ returned {type(instance).__name__}")
6        if isinstance(instance, cls):
7            instance.__init__(*args, **kwargs)
8            print(f"3. {cls.__name__}.__init__ completed")
9        return instance
10
11class MyClass(metaclass=Meta):
12    def __new__(cls, value):
13        return super().__new__(cls)
14
15    def __init__(self, value):
16        self.value = value
17
18obj = MyClass(42)
19# 1. Meta.__call__ for MyClass
20# 2. MyClass.__new__ returned MyClass
21# 3. MyClass.__init__ completed

The metaclass __call__ method orchestrates the __new____init__ sequence.

Common Pitfalls

  • Forgetting to call super().__new__(cls): If __new__ does not call super().__new__(cls), no instance is created and you get None or 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 _initialized flag to prevent overwriting attributes.
  • Trying to modify immutable types in __init__: You cannot change the value of int, str, or tuple in __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

Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

All Rights Reserved.