Python new vs init: Key Differences Explained
In Python object-oriented programming, creating an object is a
two-step process involving the __new__ and
__init__ methods. While developers commonly treat
__init__ as the constructor, the primary functional
difference is that __new__ is responsible for creating and
returning a new instance of a class, whereas __init__ is
responsible for initializing that newly created instance with data.
The Core Distinction
The instantiation process triggers both methods sequentially when you call a class:
instance = MyClass(arg1, arg2)Behind the scenes, Python translates this call into:
instance = MyClass.__new__(MyClass, arg1, arg2)
if isinstance(instance, MyClass):
MyClass.__init__(instance, arg1, arg2)__new__: The True
Constructor
- Role: Allocates memory and constructs the actual object.
- Arguments: Takes the class itself
(
cls) as its first parameter, followed by any arguments passed to the class constructor. - Return Value: Must return a newly created object
instance (typically by calling
super().__new__(cls, ...)). - Execution: It is a static method (handled specially
by the interpreter so you don't need the
@staticmethoddecorator) that runs before__init__.
__init__: The
Initializer
- Role: Configures the instance by assigning initial attributes and running setup logic.
- Arguments: Takes the newly created instance
(
self) as its first parameter, along with constructor arguments. - Return Value: Must return
None. Returning any value other thanNoneraises aTypeError. - Execution: It is an instance method that runs
after
__new__has successfully returned an instance of the class.
Key Behavioral Differences
1. Conditional Execution of
__init__
__init__ is only invoked if __new__ returns
an instance of the class in which it is defined. If __new__
returns an instance of a different class, or returns an existing
instance from a cache, Python bypasses __init__ entirely
for that call.
2. When to Override
__new__
In standard day-to-day Python programming, overriding
__init__ is sufficient. You only need to override
__new__ in specialized scenarios:
- Subclassing Immutable Types: Built-in immutable
types such as
int,str,float, ortuplecannot be modified in__init__because their values are fixed at creation time. Customizing them requires intercepting creation inside__new__. - Implementing Design Patterns: Patterns like the Singleton (restricting a class to a single instance) or Object Pooling require controlling whether a new object is actually created or if an existing reference is returned.
- Metaclasses and Code Generation: Intercepting object generation dynamically before the instance comes into existence.
Summary
| Feature | __new__ |
__init__ |
|---|---|---|
| Purpose | Creates the object instance | Initializes the created object |
| First Parameter | cls (the class) |
self (the instance) |
| Return Value | The newly created instance | None |
| Execution Order | First | Second |
| Common Use Case | Singletons, immutable subclasses | Setting instance attributes |