Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python: always use __new__ instead of __init__?

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.

like image 618
EoghanM Avatar asked Jun 28 '10 10:06

EoghanM


People also ask

What does __ new __ do in Python?

The __new__() is a static method of the object class. When you create a new object by calling the class, Python calls the __new__() method to create the object first and then calls the __init__() method to initialize the object's attributes.

Is __ init __ mandatory in Python?

So, the parent class constructor is called first. But in Python, it is not compulsory that the parent class constructor will always be called first. The order in which the __init__ method is called for a parent or a child class can be modified.

Is __ new __ constructor?

Technically speaking, the constructor is a method which creates the object itself. In Python, this method is __new__ . A common signature of this method is __new__(clas, *args, **kwargs) . When __new__() is called, the class itself is passed as the first argument automatically.

Is __ init __ called automatically?

Use the __init__() method to initialize the object's attributes. The __init__() doesn't create an object but is automatically called after the object is created.


2 Answers

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__().

like image 67
Matt Anderson Avatar answered Sep 24 '22 00:09

Matt Anderson


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.

like image 28
EoghanM Avatar answered Sep 23 '22 00:09

EoghanM