You are currently viewing __init__ Vs __new__ Methods In Python – With Examples

__init__ Vs __new__ Methods In Python – With Examples

You must have seen the implementation of the __init__ method in any Python class, and if you have worked with Python classes, you must have implemented the __init__ method many times. However, you are unlikely to have implemented or seen a __new__ method within any class.

In this article, we’ll see:

  • Definition of the __init__ and __new__ methods
  • __init__ method and __new__ method implementation
  • When they should be used
  • The distinction between the two methods

__init__ Vs __new__ Method

The __init__ method is an initializer method that is used to initialize the attributes of an object after it is created, whereas the __new__ method is used to create the object.

When we define both the __new__ and the __init__ methods inside a class, Python first calls the __new__ method to create the object and then calls the __init__ method to initialize the object’s attributes.

Most programming languages require only a constructor, a special method to create and initialize objects, but Python has both a constructor and an initializer.

Let’s talk about both these methods one by one and implement these methods inside a Python class.

__new__ Method

As stated already, the __new__ method is a constructor method used to create and return an object(instance of the class).

Syntax

object.__new__(cls, *args, **kwargs)

The __new__ method’s first parameter is cls, which is a class of the object we want to create.

The *args and **kwargs parameters are not used by the __new__ method, but they must match the parameters of the class’s __init__ method.

Example

In the above code, we defined the __new__ and __init__ methods within the class Name. The __new__ method accepts the cls parameter, which is used to refer to the class Name, and when called, it prints the message and returns the class instance using the super(Name, cls).__new__(cls).

One thing to note is that the Name class is a base class, so we could have directly called the __new__ method on the object like this expression object.__new__(cls). However, the standard method is to use the super() function.

The __init__ method is then called with the instance passed to the self parameter.

Then we called the Name class (Name()), and when we run the code, we get the output shown below.

The output shows that the __new__ method is called first and then the __init__ method.

__init__ Method

As we saw in the above example, the __init__ method is called to initialize the attributes of the object as soon as the object is created.

Syntax

__init__(self, *args, **kwargs)

As a first parameter, the __init__ method accepts self, which is used to refer to the class instance.

The parameters *args and **kwargs are used to initialize the instance variable with the values stored within them.

Example

In the __init__ method, we passed the name parameter and did the same in the __new__ method to make the __new__ and __init__ method signature compatible with each other.

We called the class with the 'Sachin' argument, which will automatically invoke the __init__ method and will initialize the instance variable self.name with this value.

When we call the name attribute(instance variable) on the object name_obj, we’ll get the following output.

The name attribute(instance variable) of the name_obj is initialized to the value 'Sachin'.

Implementation

Let’s define both __new__ and __init__ methods inside the class Language.

We defined both __new__ and __init__ methods inside the class Language and created the class object, when we run the code, Python will call the __new__ method which is responsible for creating and returning the object of the class, and then calls the __init__ method which is responsible for the initialization of the object’s attributes(instance variables).

Now we can access the attributes of the object lang and year using dot notation on the object language as we did in the above code.

Every time we create a new object, the __init__ method is invoked, which means that if we don’t return super().__new__(cls), then the __init__ method will not execute and return None.

Let’s see what happens when we implement only the __init__ method inside a class.

The code works the same as the previous code which we saw at the beginning of this section.

When we instantiated the class using language = Language('Python', 1991), the expression is equivalent to the following:

If we try to print the language object after calling the __new__ and the __init__ methods using the __dict__, then we’ll get the following output:

We got an empty dictionary after calling the __new__ method because the object was created but not yet initialized, to initialize, we called the __init__ method explicitly and got the values.

When To Use

Use case of __new__

Consider the following example in which we are using the __new__ method to customize the object at the instantiation.

The above code defines the class Reverse, which inherits from the str built-in type, as well as the __new__ method that accepts a sequence. We override the __new__ method to reverse the sequence before creating the object.

The argument "GeekPython" passed to the Reverse class got reversed due to sequence[::-1] before the object is created.

This can’t be done using the __init__ method, if we try to do so, the result will be an error.

Another use case of the __new__ method is creating a Singleton (design pattern that restricts the instantiation of a class to a single instance).

In the above code, we defined the class Singleton and created a private variable __obj to store the class’s single instance, as well as a __new__ method that checks if the __ins is None, then creates a new instance and assigns it to the __ins, and returns the existing instance if the __ins is not None.

Then we printed three instances of the Singleton class named obj1obj2, and obj3 and checked to see if they were all the same.

All three instances point to the same memory address, and we can see that we got True, indicating that they are all the same.

Use case of __init__

The __init__ method is commonly used to initialize the object’s attributes with or without the default values.

The above code defines a Language class and the __init__ method, which accepts lang and year parameters with default values of "Python" and 1991, respectively.

When we call the Language class without argument, the __init__ method will set the lang and year attributes to their default values.

Difference

Now that we’ve seen the definition, syntax, and implementation of both methods, we are now able to differentiate between them.

__new__ method__init__ method
The __new__ method is called firstThe __init__ method is called after the __new__ method
Used to create and return the objectUsed to initialize the attributes of the object
It is a constructor methodIt is an initializer method
Takes class as the first parameterTakes the instance of the class as the first parameter
Can be overridden to customize the object at the instantiationProbably only be used to initialize the attributes of the object

Conclusion

Python has a concept of a constructor and an initializer method. The __new__ method is a constructor method whereas the __init__ method is an initializer method. Python first calls the __new__ method which is responsible for the object creation and then calls the __init__ method which is responsible for the initialization of the object’s attributes.


🏆Other articles you might be interested in if you liked this one

Context managers and the with statement in Python.

What is abstract base class(ABC) in Python?

Public, Protected, and Private access modifiers in Python.

What are inheritance and different types of inheritance in Python?

What is enumerate() function in Python?

Execute dynamically generated code using the exec() in Python.

Async/Await – Asynchronous programming using asyncio in Python.


That’s all for now

Keep Coding✌✌