I tipi definiscono il modo in cui le istanze vengono decapitate definendo uno o più di un (abbastanza grande) insieme di metodi. Ognuno ha il suo comportamento sottile. Vedi the docs on the pickle protocol. Nel caso di collections.defaultdict
, utilizza il metodo __reduce__
:
>>> l = collections.defaultdict(list)
>>> l.__reduce__()
(<type 'collections.defaultdict'>, (<type 'list'>,), None, None, <dictionary-itemiterator object at 0x7f031fb3c470>)
Il primo elemento della tupla c'è il tipo, e il secondo elemento è tupla di argomenti per passare al tipo quando istanziandola. Se non si esegue l'override di __reduce__
, il primo elemento verrà modificato correttamente nel tipo, ma il secondo non lo farà. Ciò causa l'errore che vedi. Un esempio di greggio di come si potrebbe risolvere il problema:
>>> 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
E 'solo un esempio di greggio perché non c'è più per decapaggio (come __reduce_ex__
) ed è tutto abbastanza intricata. In questo caso, usare __getinitargs__
potrebbe essere più conveniente.
In alternativa, si potrebbe fare il metodo __init__
di vostra classe prendere un opzionale callable, inadempiente a list
, o si potrebbe utilizzare una funzione invece di una classe:
def listdict():
return collections.defaultdict(list)
fonte
2010-10-04 13:24:18
stai usando 'pickle' o' cpickle'? – aaronasterling
Sto usando 'cPickle'. –