Python __new__ Method
Last modified April 8, 2025
This comprehensive guide explores Python's __new__ method, the
special method responsible for object creation. We'll cover basic usage,
immutable objects, singletons, metaclasses, and practical examples.
Basic Definitions
The __new__ method is a static method that creates and returns a
new instance of a class. It is called before __init__ and is
responsible for object allocation.
Key characteristics: it must accept the class as first argument (conventionally
named cls), returns the new instance, and can be overridden to
customize object creation. Unlike __init__, it controls creation.
Basic __new__ Implementation
Here's the simplest implementation showing __new__'s role in the
object creation lifecycle. It demonstrates how it works with __init__.
class Example:
def __new__(cls, *args, **kwargs):
print("__new__ called")
instance = super().__new__(cls)
return instance
def __init__(self, value):
print("__init__ called")
self.value = value
obj = Example(42)
print(obj.value)
This example shows the object creation sequence. __new__ creates
the instance, then __init__ initializes it. The output would show
"__new__ called" before "__init__ called".
The super().__new__(cls) call is crucial - it creates the actual
instance using the parent class's __new__ method (usually
object.__new__).
Creating Immutable Objects
__new__ is essential when creating immutable types like tuples or
custom immutable classes, where modification after creation should be prevented.
class ImmutablePoint:
def __new__(cls, x, y):
instance = super().__new__(cls)
instance._x = x
instance._y = y
return instance
@property
def x(self):
return self._x
@property
def y(self):
return self._y
def __repr__(self):
return f"Point({self.x}, {self.y})"
point = ImmutablePoint(3, 4)
print(point)
# point.x = 5 # Would raise AttributeError
This immutable point class sets coordinates during creation via __new__
and exposes them as read-only properties. Attempting to modify them would raise
an AttributeError.
The instance variables are set in __new__ before returning the
instance, making them part of the initial object state. This pattern is common
for immutable objects.
Implementing the Singleton Pattern
The Singleton pattern ensures a class has only one instance. __new__
can enforce this by controlling instance creation.
class Singleton:
_instance = None
def __new__(cls):
if cls._instance is None:
print("Creating new instance")
cls._instance = super().__new__(cls)
return cls._instance
def __init__(self):
print("Initializing Singleton")
s1 = Singleton()
s2 = Singleton()
print(s1 is s2) # True
This Singleton implementation stores the single instance in a class variable.
__new__ checks if it exists before creating a new one. All
constructor calls return the same instance.
Note that __init__ is called each time, which might reinitialize
the instance. To prevent this, you could add another flag or restructure the
code.
Customizing Object Creation with Arguments
__new__ can inspect arguments and decide whether/how to create an
instance, enabling advanced creation patterns.
class LimitedInstances:
_count = 0
MAX_INSTANCES = 3
def __new__(cls, *args, **kwargs):
if cls._count >= cls.MAX_INSTANCES:
raise RuntimeError(f"Cannot create more than {cls.MAX_INSTANCES} instances")
cls._count += 1
return super().__new__(cls)
def __del__(self):
type(self)._count -= 1
objs = [LimitedInstances() for _ in range(3)] # Works
# LimitedInstances() # Raises RuntimeError
This class limits the number of live instances to 3. __new__ checks
the count before allowing creation. The __del__ method decreases
the count when instances are garbage collected.
This pattern is useful for resource-limited scenarios like database connections or thread pools where you want to enforce instance limits.
Metaclass __new__ Method
In metaclasses, __new__ controls class creation (rather than instance
creation), allowing dynamic class modification.
class Meta(type):
def __new__(mcls, name, bases, namespace):
print(f"Creating class {name}")
namespace['version'] = 1.0
return super().__new__(mcls, name, bases, namespace)
class MyClass(metaclass=Meta):
pass
print(MyClass.version) # 1.0
This metaclass adds a version attribute to every class it creates.
The metaclass's __new__ modifies the class namespace before the
class is constructed.
Metaclass __new__ receives different arguments: the metaclass
itself, the class name, base classes, and the namespace dictionary containing
class attributes.
Best Practices
- Always call super().__new__: Unless intentionally blocking creation
- Return correct type: Ensure returned object is an instance of cls
- Consider __init__: Changes in __new__ might affect initialization
- Document behavior: Clearly document any special creation logic
- Prefer __init__ when possible: Only use __new__ when necessary
Source References
Author
List all Python tutorials.