Python 如何使用自引用和从带有插槽的类中pickle和unpickle对象?

Python 如何使用自引用和从带有插槽的类中pickle和unpickle对象?,python,pickle,slots,Python,Pickle,Slots,当对象通过其属性之一引用自身时,从具有插槽的类中pickle对象的正确方法是什么?下面是一个简单的示例,使用我当前的实现,我不确定它是否100%正确: import weakref import pickle class my_class(object): __slots__ = ('an_int', 'ref_to_self', '__weakref__') def __init__(self): self.an_int = 42 self

当对象通过其属性之一引用自身时,从具有插槽的类中pickle对象的正确方法是什么?下面是一个简单的示例,使用我当前的实现,我不确定它是否100%正确:

import weakref
import pickle

class my_class(object):

    __slots__ = ('an_int', 'ref_to_self', '__weakref__')

    def __init__(self):
        self.an_int = 42
        self.ref_to_self = weakref.WeakKeyDictionary({self: 1})

    # How to best write __getstate__ and __setstate__?
    def __getstate__(self):

        obj_slot_values = dict((k, getattr(self, k)) for k in self.__slots__)
        # Conversion to a usual dictionary:
        obj_slot_values['ref_to_self'] = dict(obj_slot_values['ref_to_self'])
        # Unpicklable weakref object:
        del obj_slot_values['__weakref__']
        return obj_slot_values

    def __setstate__(self, data_dict):
        # print data_dict
        for (name, value) in data_dict.iteritems():
            setattr(self, name, value)
        # Conversion of the dict back to a WeakKeyDictionary:
        self.ref_to_self = weakref.WeakKeyDictionary(
            self.ref_to_self.iteritems())
这可以通过以下方式进行测试:

def test_pickling(obj):
    "Pickles obj and unpickles it.  Returns the unpickled object"

    obj_pickled = pickle.dumps(obj)
    obj_unpickled = pickle.loads(obj_pickled)

    # Self-references should be kept:
    print "OK?", obj_unpickled == obj_unpickled.ref_to_self.keys()[0]
    print "OK?", isinstance(obj_unpickled.ref_to_self,
                            weakref.WeakKeyDictionary)

    return obj_unpickled

if __name__ == '__main__':
    obj = my_class()
    obj_unpickled = test_pickling(obj)
    obj_unpickled2 = test_pickling(obj_unpickled)
这是一个正确/健壮的实现吗?如果
my\u类
继承自具有
\uu插槽的类,则应如何编写
\uuuu getstate\uuuuuuuuuu
\uuuuuu setstate\uuuuuuuuu
\uuuu setstate\uuuu
内部是否因为“循环”指令而出现内存泄漏

中有一句话让我想知道pickle
my_class
对象是否能够以健壮的方式进行:

\uuuu getstate\uuuu
方法应返回表示对象状态的可拾取值,而不引用对象本身

这是否与对象本身的引用被pickle的事实相冲突


这是很多问题:任何评论、评论或建议都将不胜感激

看来原来的帖子所建议的已经足够有效了

关于PEP 307的内容:

_u_getstate_uu方法应该返回一个表示对象状态的可拾取值,而不引用对象本身


我理解这只意味着
\uuu getstate\uuu
方法必须返回一个不指向(不可点击的)原始对象的表示。因此,只要不引用原始(不可勾选)对象,返回引用自身的对象就可以了。

如果希望my_类是子类,请确保替换self。uuu slots_uuu类似于:slots=set();对于self.\uuu class.\uuuu.mro():slots.update(getattr(cls,'slots',())中的cls,我会说子类更新
self.\uuuu slots.\uuu
,所以我想子类化实际上没有问题,对吧?没有。他们没有。:-)弄清楚这一点需要一些时间,因此发表了评论。:-)正确的。这也是有道理的(
self.\uuuuu插槽\uuuuu
可以在
self
类中直接看到,没有任何隐藏)。感谢您在子类化时提到更好的插槽处理。