为了泡菜,如何在不修改原始类的情况下删除instancemethod对象 [英] How to remove instancemethod objects, for the sake of pickle, without modifying the original class
问题描述
我想持久地按住reverend.thomas.Bayes
上的对象.当然,如果我尝试直接给这些类之一腌制,我会得到:
I want to persistantly hold on to an object from reverend.thomas.Bayes
. Of course, if I try to pickle one of these classes directly, I get:
TypeError: can't pickle instancemethod objects
要解决此问题,我尝试声明了两个函数:
To work around this, I have tried declaring two functions:
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
.
Basically, I try copying the object's __dict__
, and try to remove instancemethod
s by testing the type against types.MethodType
.
然后,我将通过创建一个新的Bayes
对象,然后将其与bayes_dic
合并在一起(在取消酸洗之后)来重建该对象.
I then would reconstruct the object by creating a new Bayes
object and then merging it back together with bayes_dic
(after it is UnPickled.)
但是,我还没有开始使用第二种方法,因为在没有得到原始错误的情况下,我仍然不能腌制从prepare_bayes_for_pickle
返回的对象.
But, I haven't gotten up to the second method yet, because I still can't pickle the object that is returned from prepare_bayes_for_pickle
without getting the original error.
推荐答案
更好的解决方案是将__getstate__
方法添加到Bayes
类(以及随附的__setstate__
):
The better solution would be for you to add a __getstate__
method onto the Bayes
class (with accompanying __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
类可以随时进行酸洗和不酸洗.
Now the Bayes
class can always be pickled and unpickled without additional processing.
我确实看到该类具有self.cache = {}
映射;也许在腌制时应排除在外?如果是这种情况,请在__getstate__
中忽略它,并在__setstate__
中调用self.buildCache()
.
I do see that the class has a self.cache = {}
mapping; perhaps that should be excluded when pickling? Ignore it in __getstate__
and call self.buildCache()
in __setstate__
if that is the case.
这篇关于为了泡菜,如何在不修改原始类的情况下删除instancemethod对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!