Pregunta

Sé que para ser picklable, una clase tiene que sobrescribir __reduce__ método, y tiene que devolver cadena o tuple.

¿Cómo funciona esta función? ¿Qué uso exacto de __reduce__? ¿Cuándo se utilizará?

¿Fue útil?

Solución

Cuando intenta encurtir un objeto, puede haber algunas propiedades que no se serializan bien. Un ejemplo de esto es un mango de archivo abierto. Pickle no sabrá cómo manejar el objeto y lanzará un error.

Puede decirle al módulo Pickle cómo manejar este tipo de objetos de forma nativa dentro de una clase directamente. Veamos un ejemplo de un objeto que tiene una sola propiedad; Un mango de archivo abierto:

import pickle

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

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

Debería fallar y dar un rastreo:

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

Sin embargo, si hubiéramos definido un __reduce__ método en nuestro Test clase, Pickle habría sabido cómo serializar este objeto:

import pickle

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

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

Esto debería darte algo como: "c__main__\nTest\np0\n(S'test1234567890.txt'\np1\ntp2\nRp3\n.", que se puede usar para recrear el objeto con manijas de archivo abiertos:

print(vars(pickle.loads(saved_object)))

En general, el __reduce__ El método debe devolver una tupla con al menos dos elementos:

  1. Una clase de objeto en blanco para llamar. En este caso, self.__class__
  2. Una tupla de argumentos para pasar al constructor de clase. En el ejemplo, es una sola cadena, que es la ruta al archivo para abrir.

Consultar el documentos Para una explicación detallada de qué más el __reduce__ El método puede devolver.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top