pythoninitderived-classbase-class

does __new__ over ride __init__ in python


I have the following code:

class Demo:
    def __new__(self):
        self.__init__(self)
        print("Demo's __new__() invoked")
    def __init__(self):
        print("Demo's __init__() invoked")
                      
class Derived_Demo(Demo):
    def __new__(self):
        print("Derived_Demo's __new__() invoked")
    def __init__(self):
        print("Derived_Demo's __init__() invoked")

def main():
    obj1 = Derived_Demo()
    obj2 = Demo()

main()

I'm trying to understand the order of execution:

  1. __new__ in the derived class is called first

  2. why doesn't _init_ in the derived class called next?


Solution

  • Your code is fundamentally broken, which is why __init__ isn't being invoked as expected.

    Per the docs for __new__:

    If __new__() does not return an instance of cls, then the new instance’s __init__() method will not be invoked.

    Your __new__ doesn't explicitly return anything, so it's returning None.

    If you write it correctly (including removing explicit calls to __init__ within __new__, and explicitly delegating up the inheritance chain for Derived_Demo's __new__ and __init__), you code will work as expected:

    class Demo:
        def __new__(cls):
            print("Demo's __new__() invoked")
            return super().__new__(cls)
        def __init__(self):
            print("Demo's __init__() invoked")
    
    class Derived_Demo(Demo):
        def __new__(cls):
            print("Derived_Demo's __new__() invoked")
            return super().__new__(cls)
        def __init__(self):
            print("Derived_Demo's __init__() invoked")
            super().__init__()
    
    def main():
        obj1 = Derived_Demo()
        obj2 = Demo()
    
    main()
    

    Try it online!

    Which outputs:

    Derived_Demo's __new__() invoked
    Demo's __new__() invoked
    Derived_Demo's __init__() invoked
    Demo's __init__() invoked
    Demo's __new__() invoked
    Demo's __init__() invoked
    

    where super() based dispatch completely runs all the __new__(s) then all the __init__(s) are run on the resulting object produced by __new__.