3

pickle 化されたオブジェクトの ID を保持する方法はありますか。つまり、以下の print を使用しますTrue

import pickle

class Foo:
    pass

x = Foo()
print(x is pickle.loads(pickle.dumps(x)))          #False

LinuxボックスでcPickleとcpython 3.xを使用していますが、移植可能なものは必要ありません。

4

2 に答える 2

7

はい、可能です。ピクルス化された結果に何らかの方法で「アイデンティティ」を含める必要があります。__getnewargs__その場合、使用して__new__メソッドに既存のキャッシュされたインスタンスを返すようにするのが最も自然です。

import uuid
import weakref


class Foo(object):
    ident_cache = weakref.WeakValueDictionary()

    def __new__(cls, identity=None, **kwargs):
        if identity is None:
            identity = uuid.uuid1()
        try:
            self = cls.ident_cache[identity]
        except KeyError:
            self = super(Foo, cls).__new__(cls)
            self.__identity = identity
            self.__init__(**kwargs)
            cls.ident_cache[identity] = self
        return self

    def __getnewargs__(self):
        return (self.__identity,)

    def __init__(self, foo):
        self.foo = foo
>>> import pickle
>>> a = Foo(foo=1)
>>> b = pickle.loads(pickle.dumps(a, pickle.HIGHEST_PROTOCOL))
>>> a is b
True

重要な注意点は、プロトコル バージョン 2 (またはそれ以降、仮説上) を使用する必要があることです。それ以外の場合__new__は呼び出されないためです。これは の懸念事項であり、気にpickle.dumpsloadsません。

于 2012-12-07T17:30:26.037 に答える
1
import pickle

class Foo:
    _id_counter = 0
    def __init__(self):
        self._id = Foo._id_counter
        Foo._id_counter += 1

x = Foo()
print(x._id==pickle.loads(pickle.dumps(x))._id)     # True
于 2012-12-07T17:02:15.793 に答える