Подтвердить что ты не робот

Какое точное использование __reduce__ в Пикклере

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

Как работает эта функция? Какое точное использование __reduce__? Когда он будет использоваться?

4b9b3361

Ответ 1

Я посмотрю, смогу ли я взять удар, объясняя это.

Всякий раз, когда вы пытаетесь разжечь объект, будут некоторые свойства, которые могут не сериализоваться хорошо. Например, дескриптор открытого файла. В этом случае pickle не будет знать, как обрабатывать объект и выдает ошибку.

Вы можете сообщить модулю pickle, как обращаться с этими типами объектов изнутри непосредственно внутри класса. Давайте построим пример объекта, который имеет одно свойство; дескриптор открытого файла:

import pickle

class test(object):
    def __init__(self, file_path = 'test1234567890.txt'):
        self.some_file_i_have_opened = open(file_path, 'wb')  # An open file in write mode.

my_test = test()
# Now, watch what happens when we try to pickle this object:
pickle.dumps(my_test)

Он должен потерпеть неудачу и дать трассировку:

Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
  --- snip snip a lot of lines ---
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/copy_reg.py", line 70, in _reduce_ex
    raise TypeError, "can't pickle %s objects" % base.__name__
TypeError: can't pickle file objects

Однако, если бы мы определили метод __reduce__ в нашем test class, pickle знал бы, как сериализовать этот объект:

import pickle

class test(object):
    def __init__(self, file_path = 'test1234567890.txt'):
        self._file_name_we_opened = file_path  # Used later in __reduce__
        self.some_file_i_have_opened = open(self._file_name_we_opened, 'wb')  # An open file in write mode.
    def __reduce__(self):
        return (self.__class__, (self._file_name_we_opened, ))  # we return a tuple of class_name to call, and optional parameters to pass when re-creating

my_test = test()
saved_object = pickle.dumps(my_test)
print repr(saved_object)  # Just print the representation of the string of the object, because it contains newlines.

Это должно дать вам что-то вроде: "c__main__\ntest\np0\n(S'test1234567890.txt'\np1\ntp2\nRp3\n.", которое можно использовать для воссоздания объекта с помощью дескрипторов открытых файлов:

print vars(pickle.loads(saved_object))

Обычно большая путаница заключается в том, какой тип объекта __reduce__ должен возвращаться. в то время как вы можете прочитать немного больше о том, какой тип объекта уменьшить должен вернуться на страницы документов: http://aakashlabs.org/docs/apl/pyhelp/pydocs/library/pickle.html#pickling-and-unpickling-extension-types, но в целом он требуется кортеж как минимум 2 вещи:

  • Класс пустых объектов для вызова. В этом случае self.__class__
  • Кортеж аргументов для перехода к конструктору класса. В этом случае это единственная строка, которая является путём открытия файла.

Существуют и другие необязательные элементы, но вы должны прочитать их все в документах.

Надеюсь, что это поможет!