29

I understand how both __init__ and __new__ work. I'm wondering if there is anything __init__ can do that __new__ cannot?

i.e. can use of __init__ be replaced by the following pattern:

class MySubclass(object):
    def __new__(cls, *args, **kwargs):
        self = super(MySubclass, cls).__new__(cls, *args, **kwargs)
        // Do __init__ stuff here
        return self

I'm asking as I'd like to make this aspect of Python OO fit better in my head.

EoghanM
  • 25,161
  • 23
  • 90
  • 123
  • possible duplicate of [why defined '\_\_new__' and '\_\_init__' all in a class](http://stackoverflow.com/questions/2017876/why-defined-new-and-init-all-in-a-class) – Martijn Pieters Aug 03 '12 at 05:51
  • Old question on that topic: [Python’s use of \_\_new__ and \_\_init__ ?](http://stackoverflow.com/questions/674304/pythons-use-of-new-and-init) – Mad Scientist Jun 28 '10 at 10:15

3 Answers3

23

So, the class of a class is typically type, and when you call Class() the __call__() method on Class's class handles that. I believe type.__call__() is implemented more or less like this:

def __call__(cls, *args, **kwargs):
    # should do the same thing as type.__call__
    obj = cls.__new__(cls, *args, **kwargs)
    if isinstance(obj, cls):
        obj.__init__(*args, **kwargs)
    return obj

The direct answer to your question is no, the things that __init__() can do (change / "initialize" a specified instance) is a subset of the things that __new__() can do (create or otherwise select whatever object it wants, do anything to that object it wants before the object is returned).

It's convenient to have both methods to use, however. The use of __init__() is simpler (it doesn't have to create anything, it doesn't have to return anything), and I believe it is best practice to always use __init__() unless you have a specific reason to use __new__().

Matt Anderson
  • 19,311
  • 11
  • 41
  • 57
  • 1
    To me, this doesn't really answer the OP's question. You said that "the things that `__init__()` can do is a subset of the things that `__new__()` can do", but that's precisely the OP's point, isn't it? If that sentence is true, then `__init__()` can be safely deprecated, because anything it can do, `__new__()` can do just as well. – Ray Aug 17 '17 at 10:22
  • 1
    @Ray **Your conclusion fails to follow from your premise.** While that sentence *is* ostensibly true, `__init__()` cannot be safely deprecated for all of the obvious reasons – notably, **(A)** the need to preserve backward compatibility with the existing Python ecosystem *and* **(B)** the contractual fragility of the `__new__()` API (whose design mandates that an instance be explicitly returned) versus the `__init__()` API (whose design imposes no such constraints). `__new__()` invites API violations, which is bad; `__init__()` does *not*, which is good. – Cecil Curry Feb 08 '18 at 04:55
4

One possible answer from guido's post (thanks @fraca7):

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.

Any other similar answers?


I'm accepting this answer as a 'yes' to my own question:

I'm wondering if there is anything __init__ can do that __new__ cannot?

Yes, unlike __new__, actions that you put in the __init__ method will not be performed during the unpickling process. __new__ cannot make this distinction.

EoghanM
  • 25,161
  • 23
  • 90
  • 123
2

Well, looking for __new__ vs __init__ on google showed me this.

Long story short, __new__ returns a new object instance, while __init__ returns nothing and just initializes class members.

EDIT: To actually answer your question, you should never need to override __new__ unless you are subclassing immutable types.

Federico klez Culloca
  • 26,308
  • 17
  • 56
  • 95