During instantiation of my class, I initialize some fields that are not picklable. Thus, in order to be able to (un)pickle my classes correctly, I would like my init method to be called on unpickling. This is, it seems, the way it worked with old-style classes.
With new style classes, I need to use __new__ and __getnewargs__. Here is what I do:
import cPickle
class Blubb(object):
def __init__(self, value):
self.value = value
class Bla(Blubb):
def __new__(cls, value):
instance = super(Bla, cls).__new__(cls)
instance.__init__(value)
return instance
def __getnewargs__(self):
return self.value,
def __getstate__(self):
return {}
def __setstate__(self, dct):
pass
x = Bla(2)
print x.value
pickled = cPickle.dumps(x, 2)
x_ = cPickle.loads(pickled)
assert x_.value == 2
This would be fine, if not for the fact that obj = C.__new__(C, *args). There is now **kwargs. So I am restricted to non keyword arguments in my __new__ and __init__ methods.
Does anyone know of a way to solve this? This is really unconvenient.
The pickle protocol 2 wants to call
cls.__new__(cls, *args)by default, but there is a way around this. If you use__reduce__you can return a function which will map your arguments to__new__. I was able to modify your example to get**kwargsto work: