ZetCode

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__.

basic_new.py
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.

immutable.py
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.

singleton.py
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.

conditional_creation.py
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.

metaclass.py
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

Source References

Author

My name is Jan Bodnar, and I am a passionate programmer with extensive programming experience. I have been writing programming articles since 2007. To date, I have authored over 1,400 articles and 8 e-books. I possess more than ten years of experience in teaching programming.

List all Python tutorials.