What is the difference between `__new__` and `__init__` in Python, and when would you override `__new__`?
`__new__` allocates and returns the new object; `__init__` receives that object and populates its attributes. You rarely touch `__new__` — its main legitimate uses are subclassing immutable types like `int` or `str`, and implementing the Singleton pattern.
How to think about it
Most Python developers have never written __new__, and that’s exactly the point of the question: it tests whether you know when __init__ isn’t enough. The honest answer is narrow — you reach for __new__ for immutable types (where the value is fixed at allocation, so __init__ runs too late to change it) and for the Singleton pattern.
Object creation is a two-step protocol Python runs for you:
MyClass(args)
└─ type.__call__(MyClass, args)
├─ 1. obj = MyClass.__new__(MyClass, args) # allocate the object
└─ 2. obj.__init__(args) # populate it — only if obj is a MyClass
__new__ creates and returns the instance; __init__ fills it in. If __new__ returns something that isn’t an instance of the class, Python skips __init__ entirely. For ordinary mutable classes you never touch step 1 — Python allocates through object.__new__ automatically, and you just write __init__.
When new matters
You can’t set an int’s value inside __init__, because by then the integer already exists — its value was baked in at allocation. To build a clamped integer subtype you have to intercept __new__:
# Immutable subclass: the value must be fixed at allocation time
class ClampedInt(int):
def __new__(cls, value, lo=0, hi=100):
clamped = max(lo, min(hi, value))
return super().__new__(cls, clamped)
x, y, z = ClampedInt(150), ClampedInt(-20), ClampedInt(50)
print(f"ClampedInt(150) = {x}")
print(f"ClampedInt(-20) = {y}")
print(f"ClampedInt(50) = {z}")
print(f"type: {type(x).__name__}, isinstance int: {isinstance(x, int)}")
# Singleton: __new__ hands back the SAME instance every time
class Config:
_instance = None
def __new__(cls):
if cls._instance is None:
cls._instance = super().__new__(cls)
cls._instance.debug = False # default state, set once
return cls._instance
a = Config()
b = Config()
a.debug = True
print()
print("a is b :", a is b) # same object
print("b.debug :", b.debug) # so they share state
ClampedInt(150) = 100
ClampedInt(-20) = 0
ClampedInt(50) = 50
type: ClampedInt, isinstance int: True
a is b : True
b.debug : True
ClampedInt could only do its clamping in __new__, because once the int exists its value is frozen. And Config’s __new__ returns the cached instance instead of a fresh one, so a and b are literally the same object — set a.debug and b sees it.
A small asymmetry worth knowing
__init__ must return None — return something from it raises TypeError: __init__() should return None. __new__ is the opposite: it must return an object, and if that object isn’t an instance of cls, __init__ never runs.
The mental model
A factory line: __new__ stamps out the blank part, __init__ fills in the details. For a mutable object the blank is already usable, so you only ever write __init__. For an immutable object the value is the blank — you have to get it right at the stamp.