Question

I'm enhancing an existing class that does some calculations in the __init__ function to determine the instance state. Is it ok to call __init__() from __getstate__() in order to reuse those calculations?

Was it helpful?

Solution

To summarize reactions from Kroltan and jonsrharpe:

Technically it is OK

Technically it will work and if you do it properly, it can be considered OK.

Practically it is tricky, avoid that

If you edit the code in future and touch __init__, then it is easy (even for you) to forget about use in __setstate__ and then you enter into difficult to debug situation (asking yourself, where it comes from).

class Calculator():
    def __init__(self):
        # some calculation stuff here
    def __setstate__(self, state)
        self.__init__()

The calculation stuff is better to get isolated into another shared method:

class Calculator():
    def __init__(self):
        self._shared_calculation()   

    def __setstate__(self, state)
        self._shared_calculation()

    def _shared_calculation(self):
        #some calculation stuff here

This way you shall notice.

Note: use of "_" as prefix for the shared method is arbitrary, you do not have to do that.

OTHER TIPS

It's usually preferable to write a method called __getnewargs__ instead. That way, the Pickling mechanism will call __init__ for you automatically.

Another approach is to Customize the constructor class __init__ in a subclass. Ideally it is better to have to one Constructor class & change according to your need in Subclass

class Person:
    def __init__(self, name, job=None, pay=0):
        self.name = name
        self.job = job
        self.pay = pay

class Manager(Person):
    def __init__(self, name, pay):                   
        Person.__init__(self, name, 'title', pay)  # Run constructor with 'title'

Calling constructors class this way turns out to be a very common coding pattern in Python. By itself, Python uses inheritance to look for and call only one __init__ method at construction time—the lowest one in the class tree.

If you need higher __init__ methods to be run at construction time, you must call them manually, and usually through the superclass name as in shown in the code above. his way you augment the Superclass constructor & replace the logic in subclass altogether to your liking

As suggested by Jan it is tricky & you will enter difficult debug situation if you call it in same class

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top