Domanda

So che per essere piccante, una classe deve sovrascrivere __reduce__ metodo e deve restituire stringa o tupla.

Come funziona questa funzione? Che uso esatto di __reduce__? Quando sarà usato?

È stato utile?

Soluzione

Quando provi a sottrarre un oggetto, potrebbero esserci alcune proprietà che non serializzano bene. Un esempio di questo è un maniglia di file aperto. Pickle non saprà come gestire l'oggetto e lancerà un errore.

Puoi dire al modulo sottaceto come gestire direttamente questi tipi di oggetti all'interno di una classe. Vediamo un esempio di un oggetto che ha una singola proprietà; Un manico di file aperto:

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)

Dovrebbe fallire e dare una traccia:

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

Tuttavia, se avessimo definito un __reduce__ metodo nel nostro Test Classe, Pickle avrebbe saputo come serializzare questo oggetto:

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))

Questo dovrebbe darti qualcosa del tipo: "c__main__\nTest\np0\n(S'test1234567890.txt'\np1\ntp2\nRp3\n.", che può essere utilizzato per ricreare l'oggetto con manici di file aperti:

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

In generale, il __reduce__ Il metodo deve restituire una tupla con almeno due elementi:

  1. Una classe di oggetti vuoti da chiamare. In questo caso, self.__class__
  2. Una tuplo di argomenti da passare al costruttore di classe. Nell'esempio è una singola stringa, che è il percorso del file da aprire.

Consultare il Documenti per una spiegazione dettagliata di cos'altro __reduce__ Il metodo può tornare.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top