When (and Why) Was Python `__new__()` Introduced?
When (and why) was the Python
__new__() function introduced?
There are three steps in creating an instance of a class, e.g.
MyClass.__call__()is called. This method must be defined in the metaclass of
MyClass.__new__()is called (by
__call__). Defined on
MyClassitself. 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
__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.
The blog post
The Inside Story on New-Style Classes
(from the aptly named
http://python-history.blogspot.com) written by
Guido van Rossum (Python's BDFL) provides some good information regarding this subject.
Some relevant quotes:
New-style classes introduced a new class method
__new__()that lets the class author customize how new class instances are created. By overriding
__new__()a class author can implement patterns like the Singleton Pattern, return a previously created instance (e.g., from a free list), or to return an instance of a different class (e.g., a subclass). However, the use of
__new__has other important applications. For example, in the pickle module,
__new__is used to create instances when unserializing objects. In this case, instances are created, but the
__init__method is not invoked.
Another use of
__new__is to help with the subclassing of immutable types. By the nature of their immutability, these kinds of objects can not be initialized through a standard
__init__()method. Instead, any kind of special initialization must be performed as the object is created; for instance, if the class wanted to modify the value being stored in the immutable object, the
__new__method can do this by passing the modified value to the base class
You can read the entire post for more information on this subject.
Another post about
New-style Classes which was written along with the above quoted post has some additional information.
In response to OP's edit and the quote from the Zen of Python, I would say this.
Zen of Python was not written by the creator of the language but by Tim Peters and was published only in August 19, 2004. We have to take into account the fact that
__new__ appears only in the documentation of Python 2.4 (which was released on November 30, 2004), and this particular guideline (or aphorism) did not even exist publicly when
__new__ was introduced into the language.
Even if such a document of guidelines existed informally before, I do not think that the author(s) intended them to be misinterpreted as a design document for an entire language and ecosystem.
- → What are the pluses/minuses of different ways to configure GPIOs on the Beaglebone Black?
- → Django, code inside <script> tag doesn't work in a template
- → React - Django webpack config with dynamic 'output'
- → GAE Python app - Does URL matter for SEO?
- → Put a Rendered Django Template in Json along with some other items
- → session disappears when request is sent from fetch
- → Python Shopify API output formatted datetime string in django template
- → Shopify app: adding a new shipping address via webhook
- → Shopify + Python library: how to create new shipping address
- → shopify python api: how do add new assets to published theme?
- → Access 'HTTP_X_SHOPIFY_SHOP_API_CALL_LIMIT' with Python Shopify Module