2011-07-05 7 views
5

インスタンスメソッドが自動的にIは、Python 3でインスタンスメソッドを酸洗いする必要が両方のPython 2やPython 3これはインスタンスメソッドをピクルする正しい方法ですか?はいの場合、なぜPython 3ではそれがありませんか?

に漬け及びIは、Python 3にSteven Bethardのコード例を移植することはできない。

import copyreg 
import types 

def _pickle_method(method): 
    func_name = method.__func__.__name__ 
    obj = method.__self__ 
    cls = method.__self__.__class__ 
    return _unpickle_method, (func_name, obj, cls) 

def _unpickle_method(func_name, obj, cls): 
    for cls in cls.mro(): 
     try: 
      func = cls.__dict__[func_name] 
     except KeyError: 
      pass 
     else: 
      break 
    return func.__get__(obj, cls) 

copyreg.pickle(types.MethodType, _pickle_method, _unpickle_method) 

は、これはインスタンスメソッドをpicklingするためのメソッドばか証拠?あるいは、何かがひどく間違って行くことができますか?私はいくつかのモックアップクラスでそれをテストし、すべてがうまくいくようです。

何も問題がなければ、なぜPython 3では標準的なpickleインスタンスメソッドが使えないのですか?

+0

をすべての参照は、グローバルにアクセス可能でなければならないので。 http://www.velocityreviews.com/forums/t395502-why-cant-you-pickle-instancemethods.html –

+0

@Lennartリンクを見ると、同じスレッドを自分で見つけたことがわかります。しかし、それは方法と機能を酸洗する間に実際の違いがどうなるかをよく説明していません。私はラムダ関数のようないくつかの関数もpickle化できないことを知っていますが、その場合、不可能な場合にはエラーがスローされます。なぜメソッドのために同じではない? –

答えて

0

私は実際にpython 3.5.0で元の問題を再現することはできません。次の例を参照してください。それだけで保存

import pickle 
import sys 

class Foo: 

    @staticmethod 
    def my_func(): 
     return 'Foo.my_func' 


class Bar: 
    pass 

if __name__ == '__main__': 
    if len(sys.argv) > 1 and sys.argv[1] == 'restore': 
     print('loading pickle') 
     with open('test.pickle', 'rb') as fp: 
      restored = pickle.load(fp) 
      print(restored.baz()) 
    else: 
     print('saving pickle') 
     b = Bar() 
     b.baz = Foo.my_func 

     with open('test.pickle', 'w+b') as fp: 
      p = pickle.dump(b, fp) 

(テスト)〜/テスト$のpython test.py

:-)すぐに働くかどうかは見て、最新バージョンにチェックする価値があるかもしれませんピクルス

(テスト)〜/テスト$パイソンtest.py

ロードピクルスを復元

Foo.my_func

0

あなたはクラスのインスタンス(およびインスタンスメソッド)を酸洗したい場合は、単に上で見たようあなたは、クラスオブジェクトを削除dill ...

>>> import dill 
>>> 
>>> class Foo: 
... def bar(self, x): 
...  return self.y + x 
... def zap(self, y): 
...  self.y = y 
... y = 1 
... 
>>> f = Foo() 
>>> f.zap(4) 
>>> f.monty = 'python' 
>>> 
>>> _f = dill.dumps(f) 
>>> del Foo 
>>> del f 
>>> f = dill.loads(_f) 
>>> f.monty 
'python' 
>>> f.y 
4 
>>> 
>>> _b = dill.dumps(f.bar) 
>>> del f 
>>> bar = dill.loads(_b) 
>>> bar(4) 
8 
>>> 

dill作品を使用して...そう、あなたならば、それも動作します定義されたクラスを使わないで新しいPythonセッションを開始するか、クラス定義を変更した場合。 dillは、クラスオブジェクトのインスタンスがない場合や、使用可能なクラスインスタンスがある場合にも機能します。あなたがそれを行う方法を確認したい場合は、dillソースコードを見て:https://github.com/uqfoundation/dill

はまた、関連参照:https://stackoverflow.com/a/21345273/2379433

関連する問題