Python pickle保持对象身份

gnr*_*gnr 3 python identity pickle python-3.x

有没有办法保留腌制对象的身份,即具有以下打印True:

import pickle

class Foo:
    pass

x = Foo()
print(x is pickle.loads(pickle.dumps(x)))          #False
Run Code Online (Sandbox Code Playgroud)

我在Linux机器上使用cPickle和cpython 3.x,不需要可移植的东西.

Sin*_*ion 6

对的,这是可能的; 你需要在腌制结果中加入"身份"一些方法; 在这种情况下,最自然的使用方法__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
Run Code Online (Sandbox Code Playgroud)
>>> import pickle
>>> a = Foo(foo=1)
>>> b = pickle.loads(pickle.dumps(a, pickle.HIGHEST_PROTOCOL))
>>> a is b
True
Run Code Online (Sandbox Code Playgroud)

重要的一点是你必须使用协议版本2(或更高,假设); 因为否则,__new__永远不会被召唤.这只是一个问题pickle.dumps,loads不在乎.

  • 一个有用的例子是,当一个对象在从进程“a”传递到进程“b”的泡菜中被提及,然后进程“b”将一些信息传递回“a”,它提到了它从中获得的对象“a”,在这种情况下,“a”希望将对象视为它最初创建的对象,而不是一个新的,否则相同的对象。 (2认同)
  • 非常感谢您实际回答了这个问题,而不是“您为什么要这样做?” 回复!这非常有帮助,即使是两年后:-) (2认同)