Typen definieren, wie Instanzen davon durch die Definition eines oder mehrerer (ziemlich großer) Methoden gebeizt werden. Jeder hat sein eigenes subtiles Verhalten. Siehe the docs on the pickle protocol. Im Fall von collections.defaultdict
, verwendet es die __reduce__
Methode:
>>> l = collections.defaultdict(list)
>>> l.__reduce__()
(<type 'collections.defaultdict'>, (<type 'list'>,), None, None, <dictionary-itemiterator object at 0x7f031fb3c470>)
Das erste Element in dem Tupel gibt, ist die Art und das zweite Element ist das Tupel der Argumente mit dem Typ, übergibt, wenn es instanziieren. Wenn Sie __reduce__
nicht überschreiben, wird das erste Element korrekt in Ihren Typ geändert, das zweite Element jedoch nicht. Dies verursacht den Fehler, den Sie sehen. Ein krasses Beispiel dafür, wie man es beheben könnte:
>>> 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 ist nur ein grobes Beispiel, weil es mehr zu Beizen (wie __reduce_ex__
) und es ist alles ziemlich kompliziert. In diesem Fall kann die Verwendung von __getinitargs__
bequemer sein.
Alternativ können Sie Ihre Klasse __init__
Methode nehmen Sie eine optional aufrufbar machen, zu list
säumige oder Sie könnten nur eine Funktion statt einer Klasse verwenden:
def listdict():
return collections.defaultdict(list)
Sie verwenden 'pickle' oder' cpickle'? – aaronasterling
Ich benutze 'cPickle'. –