In Python 2, you cannot call a regular method with the first argument being something other than an instance of the class (or subclass):
class Foo(object): def __init__(self): pass Foo.__init__()
So __init__ not called because it cannot do anything but throw an exception right away. Do not try to call it more useful (although I don't think I have ever seen code use this).
Python 3 has a slightly simpler implementation of the method, and this restriction no longer applies, but the semantics of __new__ same. In any case, it makes no sense to try to run the class initializer on a foreign object.
For a more constructive answer, rather than “because it is,” answer:
Overriding __new__ is already a strange thing. By default, it returns an uninitialized object, which is a concept that Python is trying to hide. If you override it, you are likely to do something like this:
class Foo(object): def __new__(cls, some_arg): if some_arg == 15:
Imagine a Python variant that is unconditionally called __init__ by return value. I immediately see a number of problems.
When you return Bar() , should Python call Bar.__init__ (which was already called in this case) or Foo.__init__ (which for a completely different type will break any Bar guarantees)?
The answer should probably be called Bar.__init__ . Does this mean that you need to return an uninitialized instance of Bar , using the return Bar.__new__(Bar) instead? Python very rarely requires you to call dunder methods outside of using super , so that would be very unusual.
Where would Bar.__init__ arguments Bar.__init__ ? Both Foo.__new__ and Foo.__init__ are passed with the same arguments - those that are passed to type.__call__ , which Foo(...) processes. But if you explicitly call Bar.__new__ , you should not remember the arguments that you wanted to pass to Bar.__init__ . You cannot store them on the new Bar object, because that is what Bar.__init__ should do! And if you just said that it receives the same arguments that were passed to Foo , you strictly limit what types can be returned from __new__ .
Or, what if you want to return an object that already exists? Python has no way to indicate that the object is already “initialized” - since uninitialized objects are a temporary and mostly internal thing of interest to __new__ , so you would have no way not to call __init__ again.
The current approach is a bit awkward, but I don't think there is a better alternative. __new__ should create space to store a new object, and returning another type of object is just a very strange thing; this is the least surprising and most useful way that Python can handle this.
If this restriction is bothering you, remember that the whole dance of __new__ and __init__ is just the behavior of type.__call__ . You can freely define your __call__ behavior in the metaclass or just change the class for the factory function.