Is there a short enough way to call the __init__
constructor of a class during unpickling in Python 3? The usual way to do this was using __getinitargs__
like so
from __future__ import print_function import pickle class Car: def __init__(self, model, number): self.model = model self.number = number print("constructed with", model, number) # many other things to do def __getstate__(self): # intentionally returns None pass def __setstate__(self, state): pass def __getinitargs__(self): # save some information when pickling # (will be passed to the constructor upon unpickling) return self.model, self.number c = Car("toyota", 1234) d = pickle.loads(pickle.dumps(c)) print("reconstructed with", d.model, d.number)
However, the __getinitargs__
will be ignored in new style classes and in Python 3+, all classes can only be new style classes. There is the __getnewargs__
but it will pass the arguments only to the __new__
class method which is not the same. A python 2 call of the above illustrative example will result in
>> constructed with toyota 1234 >> constructed with toyota 1234 >> reconstructed with toyota 1234
while a python 3 call will error out
>> constructed with toyota 1234 Traceback (most recent call last): File "test.py", line 26, in <module> print("reconstructed with", d.model, d.number) AttributeError: 'Car' object has no attribute 'model'
and ignore the __getinitargs__
method.
I don’t think Python 3 will easily regress in that regard so hopefully I am missing something obvious.
EDIT: Replacing __getinitargs__
with __getnewargs__
does not solve the issue.
Advertisement
Answer
If you want pickle
to unpickle your object by calling Car(self.model, self.number)
, going through __init__
for initialization the same way a normal call to Car
would, then tell it to do so in a __reduce__
method:
def __reduce__(self): return (Car, (self.model, self.number))
Demo.