I have a class that inherits from defaultdict like this:
class listdict(defaultdict):
def __init__(self):
defaultdict.__init__(self, list)
I can pickle it, but when I unpickle it, this happens:
('__init__() takes exactly 1 argument (2 given)', <class 'listdict'>, (<type 'list'>,))
The class does not define any special methods of the pickle protocol. Pickling and unpickling of a normal defaultdict(list) works as expected. Can anyone enlighten me?
Types define how instances of it get pickled by defining one or more of a (fairly large) set of methods. Each has its own subtle behaviour. See the docs on the pickle protocol. In the case of
collections.defaultdict, it uses the__reduce__method:The first item in the tuple there is the type, and the second item is the tuple of arguments to pass to the type when instantiating it. If you don’t override
__reduce__, the first item will correctly change to your type, but the second item will not. This causes the error you see. A crude example of how you could fix it:It’s only a crude example because there’s more to pickling (like
__reduce_ex__) and it’s all fairly intricate. In this case, using__getinitargs__may be more convenient.Alternatively, you could make your class’s
__init__method take an optional callable, defaulting tolist, or you could just use a function instead of a class: