What is __new__ in Python?

Discover the __new__ method in Python: its role in instance creation, its difference from __init__, and practical examples to master this advanced concept.
10 min read
Believemy logo

Definition of __new__ in Python

The __new__ method is a special method (or dunder method) in Python that intervenes before the __init__ method during object creation. While __init__ is responsible for initializing an already created instance, __new__ is responsible for the actual creation of that instance in memory. It is therefore the very first step in the lifecycle of a Python object.

Concretely, when you write MyObject(), Python first calls MyObject.__new__(MyObject) to create the instance, then MyObject.__init__(instance) to initialize it. Most of the time, you don't need to override __new__, because the default behavior inherited from the class object is sufficient. However, this method becomes essential in certain advanced cases that we will explore in detail.

If you want to dive deeper into this topic and master all of object-oriented programming in Python, we recommend following our complete Python course which covers these types of advanced concepts.

 

Understanding the role of __new__ in object creation

To properly understand __new__, it is essential to distinguish the two phases of object instantiation in Python:

StepMethodRoleMethod type
1. Creation__new__Creates and returns a new instanceImplicit static method
2. Initialization__init__Configures the already created instanceInstance method

The __new__ method receives the class as its first argument (conventionally named cls), unlike __init__ which receives the instance (named self). This makes sense: at the time __new__ is called, the instance doesn't exist yet.

Good to know

__new__ is technically a static method that is treated specially by Python. It must imperatively return an instance, otherwise __init__ will never be called.

Signature of __new__

Here is the typical signature of __new__:

PYTHON
class MyClass:
    def __new__(cls, *args, **kwargs):
        instance = super().__new__(cls)
        return instance

    def __init__(self, *args, **kwargs):
        # Instance initialization
        pass

You will notice that __new__ calls super().__new__(cls) to delegate the actual creation of the object to the parent class (usually object). This instruction is what allocates memory and creates the raw instance.

 

The complete instantiation flow

Here is an example that illustrates the order in which methods are called:

PYTHON
class Demonstration:
    def __new__(cls, value):
        print(f"1. __new__ is called with cls={cls.__name__}")
        instance = super().__new__(cls)
        print(f"2. Instance created: {instance}")
        return instance

    def __init__(self, value):
        print(f"3. __init__ is called with self={self}")
        self.value = value
        print(f"4. Initialization complete, value={self.value}")

obj = Demonstration(42)
# Output:
# 1. __new__ is called with cls=Demonstration
# 2. Instance created: <__main__.Demonstration object at 0x...>
# 3. __init__ is called with self=<__main__.Demonstration object at 0x...>
# 4. Initialization complete, value=42

This flow clearly shows that __new__ always precedes __init__ and that the instance returned by __new__ is exactly the one passed to __init__ as self.

 

Practical use cases for __new__

Although overriding __new__ is an advanced case, there are several situations where this method proves essential. Here are the main use cases.

1. The Singleton pattern

The Singleton is a design pattern that guarantees a class can only have one single instance. It is one of the most classic use cases for __new__:

PYTHON
class Singleton:
    _instance = None

    def __new__(cls, *args, **kwargs):
        if cls._instance is None:
            cls._instance = super().__new__(cls)
        return cls._instance

    def __init__(self, name=None):
        if name is not None:
            self.name = name

# Testing the Singleton
a = Singleton("First")
b = Singleton("Second")

print(a is b)       # True: it's the same object
print(a.name)        # "Second" (reinitialized by the second call)
print(id(a) == id(b))  # True
Warning

Warning: even though __new__ returns the same instance, __init__ is called every time. This can cause unexpected reinitializations. To avoid this, you can add a flag to initialize only once.

Here is an improved version that avoids reinitialization:

PYTHON
class SafeSingleton:
    _instance = None
    _initialized = False

    def __new__(cls, *args, **kwargs):
        if cls._instance is None:
            cls._instance = super().__new__(cls)
        return cls._instance

    def __init__(self, name=None):
        if not SafeSingleton._initialized:
            self.name = name
            SafeSingleton._initialized = True

a = SafeSingleton("First")
b = SafeSingleton("Second")

print(a.name)  # "First" (not reinitialized)
print(b.name)  # "First"

 

2. Subclassing immutable types

Immutable types like int, str, tuple or frozenset cannot be modified after their creation. Since __init__ intervenes after creation, it is too late to change the value of an immutable object. You must therefore use __new__:

PYTHON
class PositiveInt(int):
    """An integer that is always positive (absolute value)."""

    def __new__(cls, value):
        # We transform the value BEFORE creating the object
        return super().__new__(cls, abs(value))

print(PositiveInt(-42))   # 42
print(PositiveInt(15))    # 15
print(type(PositiveInt(-7)))  # 

Here is another example with strings:

PYTHON
class UpperStr(str):
    """A string that is always uppercase."""

    def __new__(cls, content):
        return super().__new__(cls, content.upper())

text = UpperStr("hello world")
print(text)         # "HELLO WORLD"
print(type(text))   # 
Good to know

This mechanism is impossible with __init__ alone, because immutable objects are already "frozen" by the time __init__ is called. This is why __new__ is essential here.

 

3. Registry system and factory pattern

You can use __new__ to implement a registry system that automatically returns the correct subclass based on the arguments:

PYTHON
class Animal:
    _registry = {}

    def __init_subclass__(cls, animal_type=None, **kwargs):
        super().__init_subclass__(**kwargs)
        if animal_type:
            Animal._registry[animal_type] = cls

    def __new__(cls, animal_type, name):
        if cls is Animal:
            subclass = cls._registry.get(animal_type, cls)
            return super().__new__(subclass)
        return super().__new__(cls)

    def __init__(self, animal_type, name):
        self.name = name

    def speak(self):
        return "..."


class Cat(Animal, animal_type="cat"):
    def speak(self):
        return f"{self.name} says: Meow!"


class Dog(Animal, animal_type="dog"):
    def speak(self):
        return f"{self.name} says: Woof!"


# Usage
animal1 = Animal("cat", "Whiskers")
animal2 = Animal("dog", "Rex")

print(type(animal1))       # 
print(animal1.speak())     # Whiskers says: Meow!
print(type(animal2))       # 
print(animal2.speak())     # Rex says: Woof!

This pattern is very powerful for creating extensible architectures where new subclasses can be added without modifying existing code.

 

4. Instance cache (Object Pool)

You can use __new__ to reuse existing instances instead of creating new ones, which is useful for optimizing memory:

PYTHON
class Color:
    _cache = {}

    def __new__(cls, name):
        normalized_name = name.lower().strip()
        if normalized_name in cls._cache:
            return cls._cache[normalized_name]
        instance = super().__new__(cls)
        cls._cache[normalized_name] = instance
        return instance

    def __init__(self, name):
        self.name = name.lower().strip()


red1 = Color("Red")
red2 = Color("red")
red3 = Color("  RED  ")

print(red1 is red2)  # True
print(red1 is red3)  # True
print(len(Color._cache))  # 1

 

__new__ and metaclasses

The __new__ method also plays a crucial role in metaclasses. A metaclass is a class whose instances are themselves classes. The __new__ method of a metaclass therefore controls the creation of classes, not instances:

PYTHON
class MetaValidation(type):
    """Metaclass that checks that each class has a docstring."""

    def __new__(mcs, name, bases, namespace):
        if not namespace.get('__doc__'):
            raise TypeError(
                f"Class '{name}' must have a docstring."
            )
        return super().__new__(mcs, name, bases, namespace)


class MyService(metaclass=MetaValidation):
    """Main service of the application."""

    def execute(self):
        pass

# This would raise TypeError:
# class ServiceWithoutDoc(metaclass=MetaValidation):
#     pass

In this context, __new__ receives four arguments: the metaclass (mcs), the name of the class to create, its bases (parent classes) and its namespace (dict containing its attributes and methods). It is a powerful tool for validating or transforming classes during their definition.

 

Differences between __new__ and __init__

Let's summarize the fundamental differences between these two methods to avoid any confusion:

Characteristic__new____init__
First argumentcls (the class)self (the instance)
RoleCreate the instanceInitialize the instance
Return valueMust return the instanceReturns nothing (None)
Call orderCalled firstCalled second
Method typeImplicit static methodInstance method
Override frequencyRarelyVery often
Main useImmutable types, singletons, metaclassesObject configuration

 

Best practices with __new__

Here are the essential recommendations for using __new__ correctly in your Python projects:

  • Only override __new__ when necessary: in the vast majority of cases, __init__ is sufficient. Using __new__ without reason adds unnecessary complexity.
  • Always call super().__new__(cls): forgetting this call will prevent instance creation and cause errors that are difficult to diagnose.
  • Always return an instance: if __new__ does not return an instance of the class, __init__ will not be called.
  • Pass arguments correctly: make sure that *args and **kwargs are properly propagated to super().__new__() when necessary.
  • Document your usage: when you override __new__, add a docstring explaining why this override is necessary.
  • Think about inheritance compatibility: if your class will be subclassed, make sure your implementation of __new__ works correctly with child classes.
Warning

Avoid putting initialization logic in __new__. This method is intended for creating the instance, not for configuring it. Keep the separation of responsibilities between __new__ (creation) and __init__ (initialization).

Here is an example of what you should not do:

PYTHON
# ❌ Bad practice: initialization logic in __new__
class Bad:
    def __new__(cls, name, age):
        instance = super().__new__(cls)
        instance.name = name    # ❌ This should be in __init__
        instance.age = age      # ❌ This too
        return instance


# ✅ Good practice: clear separation of responsibilities
class Good:
    def __init__(self, name, age):
        self.name = name
        self.age = age

 

Special case: __new__ returning an object of a different type

An interesting and sometimes confusing behavior: if __new__ returns an object that is not an instance of the class, then __init__ will not be called:

PYTHON
class Surprise:
    def __new__(cls):
        print("__new__ called")
        return "I am a string, not an instance of Surprise"

    def __init__(self):
        print("__init__ called")

obj = Surprise()
print(obj)        # "I am a string, not an instance of Surprise"
print(type(obj))  # 
# Note: __init__ is NEVER called here

This behavior is used in certain advanced cases, but it can be a source of confusion. Keep it in mind when debugging instantiation-related issues.

 

Frequently asked questions

Question

What is the difference between __new__ and __init__ in Python?

__new__ is responsible for creating the instance in memory and receives the class (cls) as its first argument. __init__ is responsible for initializing the already created instance and receives the instance (self) as its first argument. __new__ is called before __init__ and must return an instance, while __init__ returns nothing. In daily practice, you will only need to override __init__ in the vast majority of cases.

 

Question

When should you use __new__ instead of __init__?

You should use __new__ in three main cases: when you are subclassing an immutable type (like int, str, tuple) and need to modify the value before the object is created; when you are implementing the Singleton pattern to guarantee a unique instance; and when you are working with metaclasses to control the creation of classes themselves. Outside of these cases, always prefer __init__.

 

Question

Why is __init__ not called after __new__ in some cases?

If __new__ returns an object that is not an instance of the class (or one of its subclasses), Python does not call __init__. This is a safety mechanism: __init__ expects an object of the correct type as self. If you forget to return an instance (for example by forgetting the return statement), __new__ will implicitly return None, and __init__ will not be called either.

 

Question

How can you learn to master __new__ and advanced OOP in Python?

Mastering __new__ and advanced object-oriented programming concepts in Python requires practice and structured learning. We recommend following our dedicated Python course on Believemy, which covers in depth special methods, metaclasses, design patterns and many other essential topics to become a proficient Python developer.

Related terms

Discover our python glossary

Browse the terms and definitions most commonly used in development with Python.

Share this article

Want to help us? Share this article on your networks or even better: on your site, in an article or in your newsletter.