2014-02-24 3 views
1

Я хотел бы реализовать класс (в идеале одноэлементный), для которого состояние должно быть восстановлено с использованием механизма cPickle на этапе инициализации. Для этого я написал следующий фрагмент кода:ошибка при раскраске класса из его конструктора

import cPickle 
import collections 

class Test(collections.OrderedDict): 

    path = "test.cp" 

    def __init__(self): 

     self.path = "test.cp" 

     collections.OrderedDict.__init__(self) 
     try: 
      f = open(Test.path,"rb") 
     except IOError: 
      return 
     else: 
      ud = cPickle.load(f) 
      self.update(ud) 
      f.close() 

    def save(self): 

     f = open(Test.path,"wb") 
     cPickle.dump(self,f) 
     f.close() 

if __name__ == "__main__": 
    t = Test() 
    t.save() 
    t1 = Test() 

Запуск, что сниппет производит следующее сообщение об ошибке:

Traceback (most recent call last): 
    File "C:\Documents and Settings\pellegrini\Bureau\test.py", line 31, in <module> 
    t1 = Test() 
    File "C:\Documents and Settings\pellegrini\Bureau\test.py", line 18, in __init__ 
    ud = cPickle.load(f) 
TypeError: ('__init__() takes exactly 1 argument (2 given)', <class '__main__.Test'>, ([],)) 

При наследовании от dict вместо collections.OrderedDict это работает. Из других подобных сообщений это может иметь какое-то отношение к методу __reduce__, но я не понимаю, почему и как?

У вас есть представление о том, как решить эту проблему?

Большое спасибо

Эрик

+0

Технически нет "Конструкторы", как, например, в Python. Просто метод инициализации. – Elazar

ответ

3

Я предполагаю, что OrderedDict имеет свой собственный способ сериализации.

def __init__(self, *args): 

    self.path = "test.cp" 

    collections.OrderedDict.__init__(self, *args) 

попробовать это и вы получите проблему рекурсии, потому что рассол использует __init__.

ошибка бесплатно Решение:

import cPickle 
import collections 

class Test(collections.OrderedDict): 

    path = "test.cp" 

    def __init__(self, *args): 

     self.path = "test.cp" 

     collections.OrderedDict.__init__(self, *args) 
     if not args: 
      try: 
       f = open(Test.path,"rb") 
      except IOError: 
       return 
      else: 
       ud = cPickle.load(f) 
       self.update(ud) 
       f.close() 

    def save(self): 

     with open(Test.path,"wb") as f: 
      cPickle.dump(self,f) 

if __name__ == "__main__": 
    t = Test() 
    t.save() 
    t1 = Test() 

Singleton

import pickle 
import collections 

_Test_singleton = None 

class Test(collections.OrderedDict): 

    path = "test.cp" 

    def __new__(self, *args, **kw): 
     global _Test_singleton 
     if _Test_singleton is not None: 
      return _Test_singleton 
     _Test_singleton = collections.OrderedDict.__new__(self, *args, **kw) 
     _Test_singleton.load() 
     return _Test_singleton 

    def __init__(self, *args): 
     collections.OrderedDict.__init__(self, *args) 

    def load(self): 
     try: 
      f = open(self.path,"rb") 
     except IOError: 
      return 
     else: 
      try: 
       ud = pickle.load(f) 
      finally: 
       f.close() 
      self.update(ud) 

    def save(self): 
     with open(self.path,"wb") as f: 
      pickle.dump(self,f) 


if __name__ == "__main__": 
    t = Test() 
    t.save() 
    t1 = Test() 
    assert t is t1 
+0

Я бы предложил добавить инструкции 'with'. Ведь люди, вероятно, скопируют ваш ответ. – Elazar

+0

благодарит за подсказку. Возможно, мой дизайн не очень хорош ... – Eurydice

+0

добавлен с заявлением. Ваш дизайн в порядке. Возможно, вы можете разделить загрузку и инициализацию. Это было бы моим предложением. Это также зависит от того, чего вы хотите достичь. Вам нужен [singleton] (http://en.wikipedia.org/wiki/Singleton_pattern) или состояние, которое может быть [сохранено и загружено в запущенные программы] (https://github.com/niccokunzmann/mousemove/blob /master/mousemove/config.py)? – User

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