[英]Python pickling keep object identity
Is there any way to preserve the identity of a pickled object, ie have the below print True
: 有什么方法可以保留腌制对象的身份,即具有以下打印
True
:
import pickle
class Foo:
pass
x = Foo()
print(x is pickle.loads(pickle.dumps(x))) #False
I am using cPickle and cpython 3.x on a Linux box, don't need something that's portable. 我在Linux机器上使用cPickle和cpython 3.x,不需要便携式的东西。
yes, it is possible; 对的,这是可能的; You'll need to include the "identity" in the pickled result some how;
您需要以某种方式在腌制结果中包括“身份”; the most natural being to use
__getnewargs__
and have a __new__
method return the existing, cached instance in that case. 最自然的存在使用
__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
The important note is that you must use protocol version 2 (or higher, hypothetically); 重要说明是,您必须使用协议版本2(假设更高版本)。 because otherwise,
__new__
is never called. 因为否则,永远不会调用
__new__
。 This is only a concern on pickle.dumps
, loads
doesn't care. 这仅是关于
pickle.dumps
, loads
无关紧要。
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
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.