2014-03-27 3 views
1

Я построил подкласс коллекций. Стандартный класс класса. Когда я пытаюсь unpickle объекта этого класса я получаю следующее сообщение об ошибке:травление объекта, полученного по заказуDict

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?

Большое спасибо за вашу помощь

ответ

3

Вы не читали документацию для __reduce__ достаточно тщательно:

When a tuple is returned, it must be between two and five elements long. Optional elements can either be omitted, or None can be provided as their value. The contents of this tuple are pickled as normal and used to reconstruct the object at unpickling time. The semantics of each element are:

  • A callable object that will be called to create the initial version of the object. The next element of the tuple will provide arguments for this callable, and later elements provide additional state information that will subsequently be used to fully reconstruct the pickled data.

Вы возвращаете класс как вызываемая и в качестве второго элемента, items следовательно unpickle является пытаясь передать items классу, вызвав таким образом __init__, но ваш __init__ не принимает никаких аргументов и, следовательно, вы получите сообщение об ошибке.

Вы должны либо изменить __init__, чтобы принять аргумент, либо не ставить его в качестве второго элемента, а вместо него вместо пустого кортежа.

+1

большое спасибо! Чтобы быть искренним, я читал этот раздел несколько раз, но не понимал его. С вашим ответом теперь определенно яснее. – Eurydice

Смежные вопросы