Skip to main content

Python __new__ method

Python __new__ method

The __new__ method in Python is a special dunder method that controls the creation of a new class instance, preceding the __init__ method’s initialization. As a static method, it’s pivotal for customizing object instantiation, especially with immutable types and design patterns like singletons. This article delves into its mechanics, use cases, and advanced applications.


1. What is the __new__ Method?

The __new__ method is a static method responsible for allocating memory and returning a new instance of a class, invoked before __init__.

  • Syntax: def __new__(cls, *args, **kwargs), returns an instance.
  • Default: Calls object.__new__ to create the instance.
  • Role: Prepares the object for initialization.

Technical Note: Unlike instance methods, it takes cls as its first argument, marking it as a class-level operation.


2. How __new__ Works: A Basic Example

It precedes initialization in the instantiation process.

Script:

class Example:
    def __new__(cls):
        print("Creating a new instance")
        instance = super().__new__(cls)
        return instance

    def __init__(self):
        print("Initializing the instance")

obj = Example()

Output:

Creating a new instance
Initializing the instance

Explanation: __new__ creates the instance, then __init__ initializes it.


3. Customizing __new__

It’s key for altering instance creation.

Example:

class Custom:
    def __new__(cls, value):
        print(f"Creating with value: {value}")
        instance = super().__new__(cls)
        instance.value = value  # Pre-init setup
        return instance

    def __init__(self, value):
        print("Initializing")

obj = Custom(42)
print(obj.value)

Output:

Creating with value: 42
Initializing
42

Note: __new__ can pre-set attributes before __init__.


4. Why Use __new__?

It offers precise control over instantiation:

Benefit Description
Creation Manages instance allocation.
Immutability Handles immutable types.
Patterns Enables singletons, factories.
Flexibility Customizes class-level operations.

Analogy: __new__ is like a blueprint—shaping the object before it’s built by __init__.


5. Practical Applications

A. Immutable Types

Customize immutable object creation.

class UpperString(str):
    def __new__(cls, value):
        return super().__new__(cls, str(value).upper())

s = UpperString("hello")
print(s)

Output:

HELLO

Use Case: Enforce format at creation.

B. Singleton Pattern

Ensure one instance.

class Singleton:
    _instance = None

    def __new__(cls):
        if cls._instance is None:
            cls._instance = super().__new__(cls)
        return cls._instance

s1 = Singleton()
s2 = Singleton()
print(s1 is s2)

Output:

True

Benefit: Resource sharing.

C. Factory Behavior

Create based on conditions.

class Shape:
    def __new__(cls, type_):
        if type_ == "circle":
            return super().__new__(Circle)
        elif type_ == "square":
            return super().__new__(Square)
        return super().__new__(cls)

class Circle(Shape):
    def __init__(self):
        self.name = "Circle"

class Square(Shape):
    def __init__(self):
        self.name = "Square"

c = Shape("circle")
s = Shape("square")
print(c.name, s.name)

Output:

Circle Square

Use Case: Dynamic instantiation.


6. Advanced Insights

Aspect Behavior Notes
Static No self Operates on cls.
Return Any object Not limited to cls.
Metaclasses Enhanced control Works with type.

Example (Metaclass):

class MetaSingleton(type):
    _instances = {}
    def __call__(cls, *args, **kwargs):
        if cls not in cls._instances:
            cls._instances[cls] = super().__new__(cls)
        return cls._instances[cls]

class Single(metaclass=MetaSingleton):
    pass

s1 = Single()
s2 = Single()
print(s1 is s2)

Output:

True

Tip: Use super() for proper inheritance.


7. Golden Rules for Using __new__

  • Return Instance: Always return an object.
  • Use Super: Call super().__new__.
  • Target Needs: Use for immutable types, singletons.
  • Avoid Overuse: Prefer __init__ for initialization.
  • Don’t Skip: Ensure creation completes.

8. Conclusion

The __new__ method is a powerful tool in Python’s object creation process, offering control over instance allocation. From shaping immutable types to enforcing singletons, it extends beyond __init__’s reach—demanding careful use for clarity. Mastering __new__ unlocks advanced instantiation techniques.

Final Tip: "See __new__ as your object’s architect—crafting its form before the walls go up."

Comments