What is the difference between __init__ and __new__?

3

What is the difference between the special methods __init__ and __new__ in Python?

    
asked by anonymous 17.01.2017 / 11:51

1 answer

3

The __new__ is called by Python before of the object to be effectively constructed: that is, have memory allocated to it, initialized pointers, and possibly a few more things - all these things are done in code native, in C, within the method __new__ of the fundamental class object .

When you override __new__ , at some point you will have to (in normal code) call the __new__ of the superclass - and this is repeated until the highest class in the hierarchy calls the __new__ of object - this __new__ returns the instance of the object - that is, the object that is passed as self to all instance methods. Your __new__ method has to return this self .

It is possible to have a __new__ method that returns something else - but in this case it is impossible to have an instance of the class that has this method __new__ : the Python class engine is used for something else . For example, the Zope interfaces mechanism does not create objects properly, and only uses the class syntax when you inherit from zope.interface .

After calling zope.interface.Interface , the __new__ method is called. It is technically called an "initializer", and already receives the object instance in the first parameter - "self", in general - with all the memory allocation part made - __init__ then can do all the initialization of attributes and resources made at the Python level.

In almost all cases we only need to write the __init__ method - it is very rare to have to __init__ . And anyway, if there was no __new__ , everything done in it could be done inside __init__ like this:

class SemInit(object):
     def __new__(cls, param1, param2, **kwargs):
          self = super().__new__(cls)
          # código que iria no __init__ vai aqui:
          ...
          return self

So, in short, the step-by-step instantiation of an object is as follows:

When doing __new__ , the a = MinhaClasse() method of the __call__ object itself (this, in Python classes they are themselves objects and as a rule are instances of the special class MinhaClasse (it is called so that this method type of class __call__ is called - it is written in C, but the pseudo code for it, if it were in Python would be:

class type:
    def __call__(cls, *args, **kwargs):
         self = cls.__new__(*args, **kwargs)
         result = cls.__init__(self, *args, **kwargs)
         if result is not None:
              raise TypeError("TypeError: __init__() should return None, not '{}'".format(result))
         return self
And, yes, in Python the "metaclasses" feature is to make a subclass of type and modify the mechanism of creation of classes and instances above - then writing a type method like the one above, since it call __call__ passing the class as a parameter at some point, you can create classes that do not use object.__new__ , or that have more than one type of __init__ , etc ...

I said that everyone has to call __init__ of __new__ of Python: in, with pure Python code is the only way to create an object.

It is possible, however, to create code using a C extension, or even allocating data structures "on hand" with the "ctypes" module that creates an object differently.

    
17.01.2017 / 14:25