Я знаю, что для того, чтобы быть picklable, класс должен перезаписать метод __reduce__
, и он должен возвращать строку или кортеж.
Как работает эта функция?
Какое точное использование __reduce__
? Когда он будет использоваться?
Я знаю, что для того, чтобы быть picklable, класс должен перезаписать метод __reduce__
, и он должен возвращать строку или кортеж.
Как работает эта функция?
Какое точное использование __reduce__
? Когда он будет использоваться?
Я посмотрю, смогу ли я взять удар, объясняя это.
Всякий раз, когда вы пытаетесь разжечь объект, будут некоторые свойства, которые могут не сериализоваться хорошо. Например, дескриптор открытого файла. В этом случае 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__
Существуют и другие необязательные элементы, но вы должны прочитать их все в документах.
Надеюсь, что это поможет!