When (and why) was the Python __new__()
function introduced?
There are three steps in creating an instance of a class, e.g. MyClass()
:
MyClass.__call__()
is called. This method must be defined in the metaclass ofMyClass
.MyClass.__new__()
is called (by__call__
). Defined onMyClass
itself. This creates the instance.MyClass.__init__()
is called (also by__call__
). This initializes the instance.
Creation of the instance can be influenced either by overloading __call__
or __new__
. There usually is little reason to overload __call__
instead of __new__
(e.g. Using the __call__ method of a metaclass instead of __new__?).
We have some old code (still running strong!) where __call__
is overloaded. The reason given was that __new__
was not available at the time. So I tried to learn more about the history of both Python and our code, but I could not figure out when __new__
was introduced.
__new__
appears in the documentation for Python 2.4 and not in those for Python 2.3, but it does not appear in the whathsnew of any of the Python 2 versions. The first commit that introduced __new__
(Merge of descr-branch back into trunk.) that I could find is from 2001, but the 'back into trunk' message is an indication that there was something before. PEP 252 (Making Types Look More Like Classes) and PEP 253 (Subtyping Built-in Types) from a few months earlier seem to be relevant.
Learning more about the introduction of __new__
would teach us more about why Python is the way it is.
Edit for clarification:
It seems that class.__new__
duplicates functionality that is already provided by metaclass.__call__
. It seems un-Pythonic to add a method only to replicate existing functionality in a better way.
__new__
is one of the few class methods that you get out of the box (i.e. with cls
as first argument), thereby introducing complexity that wasn't there before. If the class is the first argument of a function, then it can be argued that the function should be a normal method of the metaclass. But that method did already exist: __call__()
. I feel like I'm missing something.
There should be one-- and preferably only one --obvious way to do it.