2017-12-27 15 views
1

functoolsからcmp_to_key()を使用して、比較関数をキー関数に変換するSortedListWithKeyをpickleしようとしています。 しかし、cmp_to_key()は私のオブジェクトを読み込み不能にするようですが、次のエラーが出ます:TypeError:functools.KeyWrapperオブジェクトをpickleできませんPickle functoolsラッパーエラー:functools.KeyWrapperオブジェクトをpickleできません

どうすれば修正できますか?これは、エラーを再現するコードサンプルです。

import pickle 
from functools import cmp_to_key 
from sortedcontainers import SortedListWithKey 

def order_fun(a, b): 
    if abs(a[0]-b[0]) < 1e-8: 
     return 0 
    elif a[0]-b[0] > 0: 
     return 1 
    else: 
     return -1 

pickle.loads(pickle.dumps(SortedListWithKey([[1,2], [3,4]], key=cmp_to_key(order_fun)))) 

ありがとうございました!

注:酸洗は、cmp_to_key()関数を使用せずに正常に機能しますが、私の機能はキー機能ではないので、必要です。

+0

発電機を漬けすることができますか?多分try: 'list(SortedListWithKey(...))'?参照してください:https://stackoverflow.com/questions/7180212/why-cant-generators-be-pickled#7180424私はそれが発電機に変わると思う 'キー' kwargを使用して? – jmunsch

+0

非常に古い質問ですが、すべてのオブジェクトを節約することはできません。基本的なオブジェクトに変換してみてください。 – Sraw

+0

(任意の種類の)関数をピクルすることはできません。しかし、それを行うことができなければならない['dill'](https://pypi.python.org/pypi/dill/0.2.7.1)という名前のモジュールがあります。 – martineau

答えて

2

cmp_tp_keynow written in Cであると思われ、返すクラスはpickleableでもサブクラス化もできません。しかし、元の純粋なPythonバージョンはstill maintained in the sourceであり、非常に簡単です。あなたの例でこれを使用すると、正しく動作します。もちろん、明白な欠点は、純粋なPythonのバージョンが遅いですが、the difference is not hugeです。ここで

はあなたの例の作業バージョンです:

import pickle 
from sortedcontainers import SortedListWithKey 

def order_fun(a, b): 
    if abs(a[0]-b[0]) < 1e-8: 
     return 0 
    elif a[0]-b[0] > 0: 
     return 1 
    else: 
     return -1 

class KeyFunc(object): 
    __slots__ = ['obj'] 
    def __init__(self, obj): 
     self.obj = obj 
    def __lt__(self, other): 
     return order_fun(self.obj, other.obj) < 0 
    def __gt__(self, other): 
     return order_fun(self.obj, other.obj) > 0 
    def __eq__(self, other): 
     return order_fun(self.obj, other.obj) == 0 
    def __le__(self, other): 
     return order_fun(self.obj, other.obj) <= 0 
    def __ge__(self, other): 
     return order_fun(self.obj, other.obj) >= 0 
    __hash__ = None 

sl = SortedListWithKey([[1,2], [3,4]], key=KeyFunc) 

print(sl) 

print(pickle.loads(pickle.dumps(sl))) 

は出力:

SortedListWithKey([[1, 2], [3, 4]], key=<class '__main__.KeyFunc'>) 
SortedListWithKey([[1, 2], [3, 4]], key=<class '__main__.KeyFunc'>) 
関連する問題