0
class A:
    def __new__(self):
        self.__init__(self)
        print("A's __new__() invoked") #print if called

    def __init__(self):
        print("A's __init__() invoked") #print if called

class B(A):
    def __new__(self):
        print("B's __new__() invoked") #print if called

    def __init__(self):
        print("B's __init__() invoked") #print if called

def main():
    b = B() #create an object of B
    a = A() #create an object of A

main() 

why the result is "B's new() invoked A's init() invoked A's new() invoked?I wonder why B's init method is not called.

martineau
  • 119,623
  • 25
  • 170
  • 301
  • Because you overrode `B.__new__` and didn't call `__init__`. Also, `__new__` should not take a `self` argument because there is no `self` object; it's `__new__`'s job to create it. See https://stackoverflow.com/questions/28236516/python-subclassing-a-class-with-custom-new – kaya3 Dec 21 '19 at 01:54
  • `__new__` is still given the class invoking it as an argument; whether you call it `self` or `cls` or anything else is immaterial (though using something that doesn't suggest a class goes against convention). – chepner Dec 21 '19 at 02:31
  • 1
    Most relevant here, though, is the fact that neither `A.__new__` nor `B.__new__` returns an instance of their class, so neither invokes `__init__` automatically. – chepner Dec 21 '19 at 02:32

1 Answers1

1

For a class Foo, Foo.__init__ is only invoked automatically by Foo() if Foo.__new__ returns an instance of Foo. B.__new__ returns None, so B.__init__ does not get called.

A.__init__ is only called because it is explicitly called by A.__new__, though not in a meaningful way because it is passed the class A itself, not an instance of A.

Foo() invokes type(Foo).__call__(Foo), and you can imagine that method being defined somewhat like

def __call__(cls, *args, **kwargs):
    obj = cls.__new__(cls, *args, **kwargs)
    if isinstance(obj, cls):
        cls.__init__(obj)
    return obj

If you define __new__, keep in mind the following:

  1. __new__ is a static method (though special cased by Python so that you don't need the @staticmethod decoration) that receives a class as its first argument, so the name should of the parameter should reflect that.

  2. For most use cases, the purpose of __new__ is to call super().__new__ to get an instance of the class, possibly doing some post-processing of the new object before returning it.

  3. As __init__ will be called automatically on the new instance (assuming it is of the correct type), __new__ should not call __init__ itself.

chepner
  • 497,756
  • 71
  • 530
  • 681
  • Nice answer! The thing about `__call__` makes sense, do you have a link for the actual implementation of it? – kaya3 Dec 21 '19 at 03:07
  • 1
    I feel like I've seen this Python equivalent *somewhere*, but I can't recall where. (It's quite possible I made this up myself.) The actual definition of `__call__` is buried in the C implementation (in `typeobject.c`, I think), but not in a way that makes it obvious (to me, anyway) what is going on. – chepner Dec 21 '19 at 03:20