Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

May __init__ be used as normal method for initialization, not as constructor?

Sometimes it looks reasonable to use __init__ as initialization method for already existing object, i.e.:

class A():
    def __init__(self, x):
        self.x = x

    def set_state_from_file(self, file):
        x = parse_file(file)
        self.__init__(x)

As alternative to this implementation I see the following:

class A():
    def __init__(self, x):
        self.init(x)        

    def init(self, x):
        self.x = x

    def set_state_from_file(self, file):
        x = parse_file(file)
        self.init(x)

It seems to me as over-complication of code. Is there any guideline on this situation?

Update: There is a case when it is definitely not an alternate constructor case: unpickling. During unpickling, pickle first creates an instance and only then sets its state.

like image 899
Sklavit Avatar asked Nov 14 '16 11:11

Sklavit


1 Answers

__init__ is not a constructor. It is an initialisation method, called after the instance was already constructed for you (the actual constructor method is called __new__()).

You can always call it again from your code if you need to re-initialise, this isn't a style violation. In fact, it is used in the Python standard library; see the multiprocessing.heap.Heap() implementation for example:

def malloc(self, size):
    # return a block of right size (possibly rounded up)
    assert 0 <= size < sys.maxsize
    if os.getpid() != self._lastpid:
        self.__init__()                     # reinitialize after fork

or the threading.local implementation, which uses a context manager to defer initialisation.

There is otherwise nothing special about the __init__ method itself. It is merely automatically called by type.__call__ (after creating the instance with instance = cls.__new__(cls, *args, **kwargs), cls.__init__(instance, *args, **kwargs) is called if it is available).

like image 187
Martijn Pieters Avatar answered Nov 06 '22 16:11

Martijn Pieters