Как засолить и не засолить объекты с самоссылками и от класса со слотами?

Что корректный путь состоит в том, чтобы засолить объект от класса со слотами, когда это ссылки на объект само через один из его атрибутов? Вот простой пример с моей текущей реализацией, которая я не уверен, на 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)

Действительно ли это - корректная/устойчивая реализация? как должен __getstate__ и __setstate__ будьте записаны если my_class наследованный от класса с __slots__? есть ли внутри утечка памяти __setstate__ из-за "проспекта" dict?

Существует комментарий в PEP 307, который заставляет меня задаться вопросом ли соление my_class объекты вообще возможны устойчивым способом:

__getstate__ метод должен возвратить picklable значение, представляющее состояние объекта, не ссылаясь на сам объект.

Это сталкивается с тем, что ссылка на сам объект солеа?

Это - много вопросов: любой комментарий, комментарий или совет очень ценились бы!

8
задан Martijn Pieters 2 May 2014 в 12:50
поделиться

1 ответ

Похоже, то, что предложено в исходном сообщении, работает достаточно хорошо.

Что касается того, что написано в PEP 307:

Метод __getstate__ должен возвращать picklable значение, представляющее состояние объекта, без ссылки на сам объект.

Я понимаю, что это означает только то, что метод __getstate__ просто должен возвращать представление, которое не указывает на (непикулируемый) исходный объект. Таким образом, возвращение объекта, который ссылается сам на себя, является нормальным, пока не делается ссылка на исходный (неперемещаемый) объект.

5
ответ дан 5 December 2019 в 23:13
поделиться
Другие вопросы по тегам:

Похожие вопросы: