Los tipos definen cómo las apariciones se decaparán mediante la definición de uno o más de un conjunto (bastante grande) de métodos. Cada uno tiene su propio comportamiento sutil. Ver the docs on the pickle protocol. En el caso de collections.defaultdict
, se utiliza el método __reduce__
:
>>> l = collections.defaultdict(list)
>>> l.__reduce__()
(<type 'collections.defaultdict'>, (<type 'list'>,), None, None, <dictionary-itemiterator object at 0x7f031fb3c470>)
El primer elemento de la tupla no es el tipo, y el segundo elemento es la tupla de argumentos para pasar al tipo cuando instanciar ella. Si no anula __reduce__
, el primer elemento cambiará correctamente a su tipo, pero el segundo elemento no. Esto causa el error que ves. Un crudo ejemplo de cómo se puede arreglar:
>>> import collections
>>> import pickle
>>> class C(collections.defaultdict):
... def __init__(self):
... collections.defaultdict.__init__(self, list)
... def __reduce__(self):
... t = collections.defaultdict.__reduce__(self)
... return (t[0],()) + t[2:]
...
>>> c = C()
>>> c[1].append(2)
>>> c[2].append(3)
>>> c2 = pickle.loads(pickle.dumps(c))
>>> c2 == c
True
Es sólo un ejemplo crudo porque hay más de decapado (como __reduce_ex__
) y todo es bastante complicado. En este caso, usar __getinitargs__
puede ser más conveniente.
Como alternativa, puede hacer que el método __init__
de su clase toma un opcional exigible, por defecto a list
, o usted podría utilizar una función en lugar de una clase:
def listdict():
return collections.defaultdict(list)
está usando 'pickle' o' cpickle'? – aaronasterling
Estoy usando 'cPickle'. –