为了泡菜,如何在不修改原始类的情况下删除instancemethod对象 [英] How to remove instancemethod objects, for the sake of pickle, without modifying the original class

查看:77
本文介绍了为了泡菜,如何在不修改原始类的情况下删除instancemethod对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想持久地按住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 instancemethods 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屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆