-1

からのオブジェクトを永続的に保持したいreverend.thomas.Bayes。もちろん、これらのクラスの1つを直接漬け込もうとすると、次のようになります。

TypeError: can't pickle instancemethod objects

これを回避するために、私は2つの関数を宣言しようとしました。

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

基本的に、私はオブジェクトのをコピーしてみて、タイプをに対してテストしてs__dict__を削除しようとします。instancemethodtypes.MethodType

次に、新しいオブジェクトを作成し、それを(UnPickledの後で)Bayes一緒にマージして、オブジェクトを再構築します。bayes_dic

prepare_bayes_for_pickleしかし、元のエラーを取得せずに返されたオブジェクトをまだピクルス化できないため、2番目のメソッドにはまだ到達していません。

4

3 に答える 3

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追加の処理なしで、クラスをいつでも pickle 化および unpickle 化できるようになりました。

self.cache = {}クラスにマッピングがあることがわかります。おそらくそれは酸洗時に除外する必要がありますか?その場合は無視して__getstate__電話self.buildCache()してください。__setstate__

于 2013-03-19T12:21:54.007 に答える
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))
于 2013-03-19T12:16:46.940 に答える
0

これは、丸い穴に四角いペグを取り付けるようなものです。pickle を使用して引数をピクルし、unpickle を使用して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)

このSOの質問に触発されました。

于 2013-03-19T12:21:30.067 に答える