__init__ vs __new__

__new__ is called to create new instance of class. It is commonly overwrite when we want to do some customization to object creation, such as creating singleton objects.

__init__ is called post __new__ where __init__ takes first parameter as return value of __new__ and other params from class arguments.

Example,

class A:
    def __new__(cls):
        print("Creating new instance")
        return super().__new__(cls)
 
    def __init__(self, value1, value2):
        print("In init")
        self.value1 = value1
        self.value2 = value2
 
a = A()

prints will be called and the instance will be created.