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

  • 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

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.

AltStyle によって変換されたページ (->オリジナル) /