3

静的クラス メソッドへの参照を含むオブジェクトをピクルしようとしています。Pickle は (たとえば で)存在しないためmodule.MyClass.foo、pickle できないことを示して失敗します。 次の解決策を思いつきました。ラッパー オブジェクトを使用して呼び出し時に関数を見つけ、コンテナー クラスと関数名を保存します。module.foo

class PicklableStaticMethod(object):
    """Picklable version of a static method.
    Typical usage:
        class MyClass:
            @staticmethod
            def doit():
                print "done"
        # This cannot be pickled:
        non_picklable = MyClass.doit
        # This can be pickled:
        picklable = PicklableStaticMethod(MyClass.doit, MyClass)
    """
    def __init__(self, func, parent_class):
        self.func_name = func.func_name
        self.parent_class = parent_class
    def __call__(self, *args, **kwargs):
        func = getattr(self.parent_class, self.func_name)
        return func(*args, **kwargs)

私は疑問に思っていますが、そのようなオブジェクトをピクルするためのより良い - より標準的な方法はありますか? pickleグローバルプロセスに変更を加えたくはありませんが(copy_reg例を使用)、次のパターンは素晴らしいでしょう: class MyClass(object): @picklable_staticmethod def foo(): print "done."

foo特に関数から所有者クラスを抽出できなかったため、これに対する私の試みは失敗しました。私は明示的な仕様 ( など) で解決するつもりでしたが、クラスが定義されている場所でクラス@picklable_staticmethod(MyClass)を参照する方法を知りません。MyClass

どんなアイデアも素晴らしいでしょう!

よなたん

4

2 に答える 2

5

これはうまくいくようです。

class PickleableStaticMethod(object):
    def __init__(self, fn, cls=None):
        self.cls = cls
        self.fn = fn
    def __call__(self, *args, **kwargs):
        return self.fn(*args, **kwargs)
    def __get__(self, obj, cls):
        return PickleableStaticMethod(self.fn, cls)
    def __getstate__(self):
        return (self.cls, self.fn.__name__)
    def __setstate__(self, state):
        self.cls, name = state
        self.fn = getattr(self.cls, name).fn

秘訣は、クラスから静的メソッドを取得するときにクラスを引っ掛けることです。

代替手段: メタクラス化を使用して、すべての静的メソッドに.__parentclass__属性を与えることができます。次に、サブクラス化Picklerして、各サブクラス インスタンスに独自の.dispatchテーブルを指定し、グローバル ディスパッチ テーブルに影響を与えることなく変更できます ( Pickler.dispatch)。ピクルス化、ピクルス化解除、およびメソッドの呼び出しは、少し高速になる可能性があります。

于 2009-12-16T13:57:50.387 に答える
0

編集:ジェイソンのコメントの後に変更。

インスタンスまたはクラスメソッドをピクルすることは不可能であるため、静的メソッドオブジェクトをピクルさせないという点でpythonは正しいと思います。そのようなオブジェクトは、そのコンテキストの外ではほとんど意味がありません:

これを確認してください:記述子のチュートリアル

import pickle

def dosomething(a, b):
    print a, b

class MyClass(object):
    dosomething = staticmethod(dosomething) 

o = MyClass()

pickled = pickle.dumps(dosomething)

これは機能し、これを行う必要があります。関数を定義し、それをピクルし、そのような関数を特定のクラスで staticmethod として使用します。

必要に応じた使用例がある場合は、書き留めてください。喜んで検討させていただきます。

于 2009-12-16T13:19:31.477 に答える