1

我建立了 collections.OrderedDict 标准类的子类。当我尝试 unpickle 此类的对象时,出现以下错误:

Traceback (most recent call last):
  File "pickle.py", line 29, in <module>
    print cPickle.load(f)
TypeError: ('__init__() takes exactly 1 argument (2 given)', <class '__main__.ConfiguratorsDict'>, ([['toto', 20]],))

为了理解这种行为的原因,我缩小了 collections.OrderedDict 的范围,以获得以下触发 aformentionned 错误的最小代码。这里是:

import cPickle

class OrderedDict(dict):
    def __reduce__(self):
        items = [[k, self[k]] for k in self]
        inst_dict = vars(self).copy()
        for k in vars(OrderedDict()):
            inst_dict.pop(k, None)
        if inst_dict:
            return (self.__class__, (items,), inst_dict)

        return self.__class__, (items,)

class ConfiguratorsDict(OrderedDict):

    def __init__(self):
        OrderedDict.__init__(self)

        self._myspec = "blabla"

if __name__ == "__main__":

    f = open("test.pickle","wb")
    c = ConfiguratorsDict()
    c["toto"] = 20
    cPickle.dump(c,f)
    f.close()    
    f = open("test.pickle","rb")
    print cPickle.load(f)
    f.close()

在这一点上,我真的不明白那里出了什么问题。我对泡菜机制有什么误解还是与 OrderedDict 相关的问题?

非常感谢你的帮助

4

1 回答 1

3

您没有__reduce__仔细阅读文档:

返回元组时,它的长度必须在 2 到 5 个元素之间。可选元素可以省略,None也可以作为它们的值提供。这个元组的内容被正常腌制,并用于在解腌时重建对象。每个元素的语义是:

  • 将被调用以创建对象的初始版本的可调用对象。元组的下一个元素将为这个 callable 提供参数,后面的元素提供额外的状态信息,这些信息随后将用于完全重建腌制数据。

您将类返回为可调用的,并作为第二个元素返回,items因此 unpickle 试图将 传递items给类,从而调用__init__,但您__init__不接受任何参数,因此您会收到错误消息。

您必须更改__init__以接受参数或避免将其作为第二个元素而您是一个空元组。

于 2014-03-27T14:45:51.863 回答