The Distinction And Association Between __new__ And __init__ In Python

The difference between __new__ and __init__ is mainly focus on self distinction and new-style and old-style python class definition. This article will show their difference with examples.

1. Difference Between __new__ And __init__ Method.

  1. __new__ : Responsible for object creation, when __new__ method is called, it will return an instance of the current object.
  2. __init__ : Responsible for object initialization, __init__ method will be called after object creation, this method do not  return value.

2. In A Python Class, If __new__ And __init__ All Exist Then __new__ Is Called First.

Below examples will be executed in Python interactive environment. So open a terminal and input $ python or $ python3 in it. Then run below example code, you can see new is printed out.

:~$ python3
Python 3.7.1 (default, Dec 14 2018, 19:28:38) 
[GCC 7.3.0] :: Anaconda, Inc. on linux
Type "help", "copyright", "credits" or "license" for more information.

>>> class ClsTest:
...     def __init__(self):
...         print("init")
...     def __new__(cls,*args, **kwargs):
...         print("new")
... 
# you must run below code after above class definition ( after a new line with >>> ), otherwise you will get error like SyntaxError: invalid syntax
>>> ct1 = ClsTest
>>> ct1
<class '__main__.ClsTest'>
>>> ClsTest()
new

3. If __new__ Returns An Instance Of An Object, __init__ Is Implicitly Called.

>>> class ClsTest(object):
...     def __init__(self):
...         print ("init")
...     def __new__(cls,*args, **kwargs):
...         print ("new %s"%cls)
            # the __new__ method return an object, so __init__ method is called also.
...         return object.__new__(cls, *args, **kwargs)
...   
... 
>>> ClsTest()
new <class '__main__.ClsTest'>
init
<__main__.ClsTest object at 0x7fb0c2e38cc0>

4. The __new__ Method Returns The Constructed Object, But __init__ Does Not. __init__ Has No Return Value.

>>> class ClsTest(object):
...      def __init__(cls):
...              cls.x = 2
...              print ("init")
...              return cls
... 
>>> ClsTest
<class '__main__.ClsTest'>
>>> ClsTest()
init
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: __init__() should return None, not 'ClsTest'

5. If __new__ Does Not Correctly Return An Instance Of Current Class, __init__ Will Not Be Called. Even If Parent Class Defined __init__ Method.

>>> class ClsTest1(object):
...     pass
... 
# ClsTest2 __new__ method return ClsTest1 instance.
>>> class ClsTest2(ClsTest1):
...     def __init__(self):
...         print ("init")
...     def __new__(cls,*args, **kwargs):
...         print ("new %s"%cls)
...         return object.__new__(ClsTest1, *args, **kwargs)
... 
# so only __new__ method is invoked.
>>> b=ClsTest2() 
new <class '__main__.ClsTest2'>
>>> print (type(b))
<class '__main__.ClsTest1'>
>>> 
# ClsTest3 __new__ method return ClsTest2 instance.
>>> class ClsTest3(ClsTest1):
...     def __init__(self):
...         print ("init")
...     def __new__(cls,*args, **kwargs):
...         print ("new %s"%cls)
...         return object.__new__(ClsTest3, *args, **kwargs)
... 
# both __new__, __init__ method are invoked.
>>> c=ClsTest3()
new <class '__main__.ClsTest3'>
init
>>> 

6. Conclusion.

  1. Only new style python class that inherited from object has __new__ method.
  2. __new__ must have at least one parameter cls, cls represent the class to be instantiated. This parameter is provided automatically by the Python interpreter at instantiation time.
  3. __new__ must have a return value which is the instantiated instance. The instance can be parent class’s __new__ instance, or directly an instance of object’s __new__ instance.
  4. __init__ has a parameter self, which is the instance returned by this class’s __new__ method.
  5. __init__ can do some other initialization on top of __new__, and __init__ does not require a return value.
  6. If __new__ returns an instance of an object, __init__ is implicitly called.