2013-03-19 63 views
-1

我想持久保留reverend.thomas.Bayes中的對象。當然,如果我嘗試直接醃製這些類中的一個,我得到:如何在不修改原始類的情況下刪除instancemethod對象,但不修改原始類

TypeError: can't pickle instancemethod objects 

要解決這個問題,我已經試過聲明兩個功能:

import types 
from itertools import chain 
from copy import copy 
from reverend.thomas import Bayes 

def prepare_bayes_for_pickle(bayes_obj): 
    dic = copy(bayes_obj.__dict__) #I also tried using deepcopy instead of copy 
    for k in dic: 
     if type(k) == types.MethodType: 
      dic.pop(k) 
    return dic 

def reconstruct_bayes_from_pickle(bayes_dic): 
    b = Bayes() 
    # Merge b with bayes_dic, with bayes_dic taking precedence 
    dic = dict(chain(bayes_dic, b)) 
    b.__dict__ = dic 
    return b 

基本上,我嘗試複製對象的__dict__,並嘗試通過測試types.MethodType的類型來刪除instancemethod

然後我會通過創建一個新Bayes對象,然後bayes_dic合併回來在一起(在它是拆封。)

但是,我還沒有起牀第二種方法又重建對象,因爲我仍然無法醃製從prepare_bayes_for_pickle返回的對象,但未收到原始錯誤。

+0

可能重複的[如何醃一個scipy.stats分發(不能pickle instancemethod對象)](http://stackoverflow.com/questions/14235693/how-to-pickle-a-scipy-stats-distribution -cant-pickle-instancemethod-objects) – Bakuriu 2013-03-19 12:25:45

+0

但是,對所謂重複的答案只涉及對參數進行酸洗。我不認爲這對我有用,因爲我會對這個對象進行很多變種:取消所有的變異參數並且每次創建一個新對象意味着每次對象被「取消選中」時都必須重複計算。 – dg123 2013-03-19 13:18:16

+0

與其他幾乎所有的操作相比,您是否考慮過酸洗/取出文件佔用大量時間?我的意思是,即使重複計算也不是瓶頸。你應該在做出這種表述之前進行配置另外,最重要的是,我看到'Bayes'類具有'save'和'load'方法。你爲什麼不使用它們? – Bakuriu 2013-03-19 16:02:34

回答

0

k是一個關鍵,即屬性/方法名稱。你需要測試屬性本身:

if type(dic[k]) == types.MethodType: 
      ^~~~~~ here 

我更喜歡使用理解;你也應該使用isinstance

dic = dict((k, v) for k, v in bayes_obj.__dict__ 
      if not isinstance(v, types.MethodType)) 
0

這聽起來像是得到一個方釘,以適應一個圓孔。如何使用pickle來清理參數,並取消重建reverand.Thomas.Bayes對象?

>>> from collections import namedtuple 
>>> ArgList = namedtuple('your', 'arguments', 'for', 'the', 'reverand') 
>>> def pickle_rtb(n): 
...  return pickle.dumps(ArgList(*n.args)) 
... 
>>> def unpickle_rtb(s): 
...  return reverand.Thomas.Bayes(*pickle.loads(s)) 
... 
>>> s = pickle_rtb(reverand.Thomas.Bayes(1, 2, 3, 4, 5)) # note arguments are a guess 
>>> rtb = unpickle_norm(s) 

this的啓發SO問題。

2

更好的解決方案將是您添加__getstate__方法到Bayes類(具有附帶__setstate__):

import types 
from reverend.thomas import Bayes 

def Bayes__getstate__(self): 
    state = {} 
    for attr, value in self.__dict__.iteritems(): 
     if not isinstance(value, types.MethodType): 
      state[attr] = value 
     elif attr == 'combiner' and value.__name__ == 'robinson': 
      # by default, self.combiner is set to self.robinson 
      state['combiner'] = None 
    return state 

def Bayes__setstate__(self, state): 
    self.__dict__.update(state) 
    # support the default combiner (an instance method): 
    if 'combiner' in state and state['combiner'] is None: 
     self.combiner = self.robinson 

Bayes.__getstate__ = Bayes__getstate__ 
Bayes.__setstate__ = Bayes__setstate__ 

現在Bayes類總是可以進行酸洗並沒有額外的處理拆封。

我確實看到這個類有一個self.cache = {}映射;也許這應該在酸洗時排除?忽略它在__getstate__self.buildCache()__setstate__如果是這種情況。

+0

這似乎適用於酸洗,但去取消,我得到'AttributeError:'貝葉斯的對象沒有屬性'_tokenizer''。嘗試在repl中鍵入(bayes_obj._tokenizer)'(同時使用創建時沒有拆開的'bayes_obj'),返回''。 – dg123 2013-03-19 13:06:54

+0

@ user1436026:我又看了看對象;實例方法是設置爲「self.robinson」的組合器,我推測。你可以使用http://pastie.org來顯示該異常的* full *回溯嗎?默認值是將'_tokenizer'設置爲'reverend.thomas.Tokenizer'實例,該實例應該是可挑選的。 – 2013-03-19 13:19:06

+0

這是追蹤:http://pastie.org/6626181 – dg123 2013-03-19 13:35:54

相關問題