Comparison

Python __new__ vs __init__: Object Creation Explained

Comparison of Python's __new__ and __init__ methods covering call order, use cases, and common pitfalls.

{ "slug": "python-init-vs-new-explained", "title": "Python __new__ vs __init__: Object Creation Explained", "description": "Learn the difference between Python's __new__ and __init__ methods, when to override each, and common pitfalls with singletons and immutable subclasses.", "type": "comparison", "toolSlugs": ["python-repl", "class-inspector"], "keywords": ["python __new__", "python __init__", "object creation", "class instantiation", "singleton pattern", "immutable subclass", "metaclass", "dunder methods"], "content": "

Python __new__ vs __init__: Object Creation Explained

\n\n

When you write MyClass() in Python, two dunder methods run behind the scenes: __new__ and __init__. Most Python developers only ever touch __init__, but understanding both unlocks powerful patterns like singletons, immutable subclasses, and factories.

\n\n

The Core Difference

\n\n

__new__ is the constructor. It creates the instance and returns the new object. It's a static method (implicitly) that receives the class itself as its first argument.

\n\n

__init__ is the initializer. It configures an already-created instance and returns None. It receives the instance as self.

\n\n

The Call Order

\n\n

When Python evaluates MyClass(x, y), this happens:

\n\n
    \n
  1. __new__(cls, x, y) runs first and returns an instance.
  2. \n
  3. If — and only if — the returned object is an instance of cls, Python then calls __init__(instance, x, y).
  4. \n
  5. If __new__ returns something that is not an instance of cls, __init__ is skipped entirely.
  6. \n
\n\n

That last point is why factory patterns using __new__ work: return a different type and initialization is bypassed.

\n\n

Signatures Side by Side

\n\n
class MyClass:\n    def __new__(cls, *args, **kwargs):\n        instance = super().__new__(cls)\n        return instance\n\n    def __init__(self, *args, **kwargs):\n        self.args = args\n        # implicit: return None\n
\n\n

Note that __new__ takes cls (the class), while __init__ takes self (the instance). Both usually receive the same trailing arguments passed to the constructor call.

\n\n

When to Override __new__

\n\n

For regular classes, you almost never need __new__. Override it only in these cases:

\n\n

1. Singleton Pattern

\n
class Singleton:\n    _instance = None\n\n    def __new__(cls):\n        if cls._instance is None:\n            cls._instance = super().__new__(cls)\n        return cls._instance\n
\n

Watch out: __init__ still runs every time the class is called, so guard reinitialization there too.

\n\n

2. Subclassing Immutable Types

\n

Types like int, str, tuple, and frozenset are immutable — their value is baked in at creation. You cannot mutate them in __init__, so customization must happen in __new__:

\n
class PositiveInt(int):\n    def __new__(cls, value):\n        if value < 0:\n            raise ValueError(\"Must be positive\")\n        return super().__new__(cls, value)\n
\n\n

3. Metaclasses

\n

A metaclass's __new__ creates the class object itself, letting you inject attributes, register subclasses, or rewrite methods before the class exists.

\n\n

4. Factory Patterns

\n

Return a different subclass based on arguments — __init__ is skipped when the returned object isn't an instance of the requested class.

\n\n

Common Mistakes

\n\n

Forgetting to Call super().__new__()

\n
class Broken:\n    def __new__(cls):\n        pass  # returns None — no instance created!\n
\n

Without super().__new__(cls), you never actually allocate an object. The call returns None, and __init__ is silently skipped.

\n\n

Not Returning From __new__

\n

Any code path in __new__ that forgets an explicit return returns None implicitly, breaking construction.

\n\n

Passing Extra Args to object.__new__

\n

object.__new__ accepts only cls. If you also override __init__, forwarding extra arguments to super().__new__(cls, *args) raises TypeError in modern Python. Pass only cls unless the parent is an immutable builtin.

\n\n

Assuming __init__ Runs Once

\n

In singleton patterns, __init__ re-runs on every call. Use a sentinel:

\n
def __init__(self, value):\n    if hasattr(self, \"_initialized\"):\n        return\n    self._initialized = True\n    self.value = value\n
\n\n

Quick Comparison Table

\n\n\n \n \n \n \n \n \n
Aspect__new____init__
PurposeCreate instanceInitialize instance
First argclsself
ReturnsNew objectNone
Runs whenAlwaysOnly if __new__ returned cls instance
Override forSingletons, immutables, metaclassesSetting attributes on regular classes
\n\n

Bottom Line

\n\n

Reach for __init__ 99% of the time. Reach for __new__ when you need to control whether or which instance gets created — not just how it's configured.

" }
python __new__ python __init__ object creation singleton pattern immutable subclass metaclass dunder methods

Explore 300+ Free Tools

Utilko has tools for developers, writers, designers, students, and everyday users — all free, all browser-based.