Python pickling keep object identity

烈酒焚心 提交于 2019-12-24 00:18:39

问题


Is there any way to preserve the identity of a pickled object, i.e. have the below print 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.


回答1:


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.

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); because otherwise, __new__ is never called. This is only a concern on pickle.dumps, loads doesn't care.




回答2:


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


来源:https://stackoverflow.com/questions/13767474/python-pickling-keep-object-identity

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!