Python pickle保持对象身份

时间:2012-12-07 16:53:15

标签: python python-3.x identity pickle

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

import pickle

class Foo:
    pass

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

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

2 个答案:

答案 0 :(得分:5)

是的,有可能;你需要在腌制结果中加入“身份”一些方法;在这种情况下,使用__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.dumps的一个问题,loads并不关心。

答案 1 :(得分: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