1

次のコードは正しく実行されます。

import pickle

class MyClass():   
    def __init__(self, arg):
        self.arg = arg

a = MyClass('my arg')
with open('/home/mahikeulbody/mypickle', 'wb') as file:
    pickle.dump(a, file)

しかし、マルチトンクラスを取得するためにデコレータを追加します:

import pickle

def multiton(cls):
    instances = {}
    def getinstance(arg):
        if arg not in instances:
            instances[arg] = cls(arg)
        return instances[arg]
    return getinstance

@multiton
class MyClass():   
    def __init__(self, arg):
        self.arg = arg

a = MyClass('my arg')
with open('/home/michel/mypickle', 'wb') as file:
    pickle.dump(a, file)

次のエラーが発生します。

pickle.dump(a, file)
_pickle.PicklingError: Can't pickle <class '__main__.MyClass'>: it's not the same object as __main__.MyClass

なにが問題ですか ?

4

2 に答える 2

2

Pickleは、クラスを直接ロードできる必要があります。デコレータはクラスをファクトリ関数に置き換え、pickleがクラス自体をインポートできないようにします。

デコレータではなく、別のファクトリ関数を使用して、「プライベート」クラスを返します(ただし、直接インポート可能です)。

class _MyClass():   
    def __init__(self, arg):
        self.arg = arg

def MyClass(arg, instances={}):
    if arg not in instances:
        instances[arg] = _MyClass(arg)
    return instances[arg]
于 2013-01-24T17:26:52.893 に答える
0

これを行うには、Pythonでほとんどすべてをシリアル化できるdillを使用します。

>>> def multiton(cls):
...     instances = {}
...     def getinstance(arg):
...         if arg not in instances:
...             instances[arg] = cls(arg)
...         return instances[arg]
...     return getinstance
... 
>>> @multiton
... class MyClass():   
...     def __init__(self, arg):
...         self.arg = arg
... 
>>> import dill
>>>                       
>>> a = MyClass('my arg')
>>> b = dill.loads(dill.dumps(a))
>>> a
<__main__.MyClass instance at 0x4d64558>
>>> b
<__main__.MyClass instance at 0x4d64800>

Dillには、コードが失敗したときにピクルスが失敗する原因を理解するのに役立ついくつかの優れたツールもあります。

于 2013-10-17T14:11:31.483 に答える