Home Tutorials OOP

OOP

__new__ vs __init__: Object Creation Versus Initialization in Python

Pyford Notes July 6, 2026 8 min read
Key points
  • Calling MyClass(args) first calls __new__(cls, args) to create the instance, then calls __init__(instance, args) on the result to configure it.
  • __init__ only runs automatically if __new__ actually returns an instance of cls (or a subclass of it) -- returning something else skips __init__ entirely.
  • Subclassing an immutable built-in like str, int, or tuple to customise the actual value requires overriding __new__, since __init__ runs too late to change it.
  • A singleton pattern -- always returning the same instance -- is implemented by overriding __new__, not __init__, since __init__ can't prevent creation.

Instantiation is two separate steps, not one

Writing MyClass(args) looks like one operation, but it's actually two method calls in sequence. Python first calls __new__(cls, *args, **kwargs), a static method (implicitly) whose job is to create and return a new, bare object. If that object is an instance of cls (or a subclass of it), Python then calls __init__(instance, *args, **kwargs) on it, whose job is to set up its attributes. The default object.__new__ and object.__init__ handle both steps invisibly for ordinary classes, which is why most code never needs to think about this split at all:

class Traced:
    def __new__(cls, *args, **kwargs):
        print(f"__new__ creating a {cls.__name__}")
        instance = super().__new__(cls)
        return instance

    def __init__(self, name):
        print(f"__init__ configuring with name={name!r}")
        self.name = name

t = Traced("example")
# __new__ creating a Traced
# __init__ configuring with name='example'

__new__ receives the class as its first argument (conventionally cls, mirroring how __init__ receives the instance as self), because at the point __new__ runs, no instance exists yet for it to be a method of.

Why __init__ alone can't fix an immutable subclass

For most classes this split is invisible because __init__ can do everything needed — the instance already exists by the time it runs, and setting attributes on it is enough. Immutable built-in types break that assumption: their value is fixed at creation time, before __init__ ever runs, so subclassing them to customise the value itself requires overriding __new__ instead:

class PositiveInt(int):
    def __new__(cls, value):
        if value <= 0:
            raise ValueError(f"must be positive, got {value}")
        return super().__new__(cls, value)   # int's actual value is fixed HERE

# Trying to enforce this in __init__ instead would not work:
class BrokenPositiveInt(int):
    def __init__(self, value):
        if value <= 0:
            raise ValueError("too late -- the int's value was already fixed by __new__")
        # by the time __init__ runs, the underlying int value is already immutable

p = PositiveInt(5)     # works fine
# PositiveInt(-1)       # raises ValueError, caught in __new__ before the int exists

An int's numeric value is baked in when the object is constructed, not settable afterward the way a normal attribute is, which is exactly why validation or transformation of the value itself has to happen in __new__, before that value is locked in.

A singleton built on __new__

A singleton — a class that only ever produces one shared instance, however many times it's "constructed" — is a natural fit for __new__, because __init__ has no way to prevent an instance from being created in the first place; by the time __init__ runs, __new__ has already committed to returning something:

class AppConfig:
    _instance = None

    def __new__(cls):
        if cls._instance is None:
            cls._instance = super().__new__(cls)
            cls._instance._loaded = False
        return cls._instance

    def __init__(self):
        if not self._loaded:
            print("loading configuration from disk")
            self.settings = {"debug": False}
            self._loaded = True

a = AppConfig()   # prints "loading configuration from disk"
b = AppConfig()   # __init__ runs again, but the _loaded guard skips reloading
print(a is b)      # True -- the exact same object both times

Note that __init__ still runs on every call to AppConfig(), even the second one, since Python always calls it when __new__ returns an instance of the class — the _loaded guard inside __init__ is what prevents redoing the expensive setup work a second time.

The one rule: __new__ must return an instance

If __new__ returns an object that is not an instance of cls (or one of its subclasses), Python skips calling __init__ entirely — there's no instance of the "right" class for __init__ to configure. This is occasionally used deliberately, to have a class's constructor return a wholly different type:

class MaybeCached:
    _cache = {}

    def __new__(cls, key):
        if key in cls._cache:
            return cls._cache[key]       # returning an EXISTING object
        instance = super().__new__(cls)
        cls._cache[key] = instance
        return instance

    def __init__(self, key):
        print(f"__init__ running for key={key!r}")   # runs every time, cached or not
        self.key = key

This is a sharp edge worth remembering: because the returned object here is still an instance of cls, __init__ runs again on it every time, which can silently re-run setup logic on an object you intended to be immutable after first creation — worth guarding against explicitly, the same way the singleton example above did with _loaded.

The same split, one level up: metaclasses

The identical two-step pattern reappears one level up the class hierarchy: a metaclass's __new__ creates the class object itself, and its __init__ configures that class object, mirroring exactly how an ordinary class's __new__ and __init__ relate to instances. Recognising the pattern once makes it immediately familiar the second time it shows up. The full construction sequence, including where __init_subclass__ and metaclass hooks fit in, is laid out in the data model reference for __new__.