57

ピクル可能にするためには、クラスがメソッドを上書きする必要__reduce__があり、文字列またはタプルを返す必要があることを私は知っています。

この機能はどのように機能しますか? の正確な使い方は__reduce__? いつ使用されますか?

4

1 に答える 1

83

オブジェクトをピクルしようとすると、適切にシリアル化されないプロパティがいくつかある可能性があります。この 1 つの例は、開いているファイル ハンドルです。Pickle はオブジェクトの処理方法を認識せず、エラーをスローします。

これらのタイプのオブジェクトをクラス内でネイティブに処理する方法を pickle モジュールに直接伝えることができます。単一のプロパティを持つオブジェクトの例を見てみましょう。開いているファイル ハンドル:

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)

失敗し、トレースバックが表示されます。

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いれば、pickle はこのオブジェクトをシリアル化する方法を知っていたでしょう。

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

これにより、次のようなものが得られるはずです: "c__main__\nTest\np0\n(S'test1234567890.txt'\np1\ntp2\nRp3\n."、これを使用して、開いているファイル ハンドルを使用してオブジェクトを再作成できます。

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

一般に、__reduce__メソッドは少なくとも 2 つの要素を持つタプルを返す必要があります。

  1. 呼び出す空のオブジェクト クラス。この場合、self.__class__
  2. クラス コンストラクターに渡す引数のタプル。この例では、開くファイルへのパスである単一の文字列です。

メソッドが他に返すことができるものの詳細な説明については、ドキュメントを参照してください。__reduce__

于 2013-11-09T10:13:18.873 に答える