10.1 すべては自分の思い通りに!
時々、自分のオブジェクトには色んな種類のサービスオブジェクトへの参照が たくさん保存されていることがあって、それらをネットワーク経由で送信したくない または送信できない場合があります。ファイル、データベースへの参照など。
シリアライズがそのようなケースでも機能するように、クラスがその シリアライズを自分で管理する機能を持たせることが考案されました。そのために 特殊なメソッドが使われます:__reduce__()、 __getstate__()、__setstate__()。これらのメソッドは オブジェクトがどのようにシリアライズおよび復元されるべきかを指定するのに役立ちます。
管理されたシリアライズの主要なメソッド:
-
__reduce__(): オブジェクトがどのように シリアライズされるべきかを指定します。 -
__getstate__(): シリアライズするためのオブジェクトの状態を返します。 -
__setstate__(self, state): 状態からオブジェクトを復元します。
これらのメソッドについて詳しく説明して、どのように組み合わせて使うかをお伝えします。
10.2 メソッド __reduce__()
メソッド __reduce__() は、オブジェクトがどのように シリアライズおよびデシリアライズされるべきかを指定するタプルを返します。 タプルは通常以下を含みます:
- オブジェクトを復元するために使用される関数またはクラスへの参照。
- その関数またはクラスの引数のタプル。
- 追加のオブジェクトの状態(必要に応じて)。
例:
import pickle
class CustomClass:
def __init__(self, value):
self.value = value
def __reduce__(self):
return (self.__class__, (self.value,))
def __repr__(self):
return f"CustomClass(value={self.value})"
# オブジェクトの作成
obj = CustomClass(42)
# オブジェクトのシリアライズ
serialized_obj = pickle.dumps(obj)
print("シリアライズされたオブジェクト:", serialized_obj)
# オブジェクトのデシリアライズ
deserialized_obj = pickle.loads(serialized_obj)
print("デシリアライズされたオブジェクト:", deserialized_obj)
デフォルトでは、__reduce__() メソッドは以下のような動作をします:
class CustomClass:
def __init__(self, value):
self.value = value
def __reduce__(self):
# クラスの定義
cls = self.__class__
# コンストラクタの引数
args = (self.value,)
# オブジェクトの状態
state = self.__dict__
return (cls, args, state)
それは3つのオブジェクトからなるタプルを返します:
現在のクラスへの参照コンストラクタの引数 (タプル)オブジェクトの現在の状態への参照
これが望む動作であれば、__reduce__() をオーバーライドする必要はないです。
10.3 状態の読み込みと書き込み
メソッド __getstate__() と __setstate__()
これらは、シリアライズとデシリアライズの際にオブジェクトの状態を管理するために使用されます。
-
__getstate__(): シリアライズするべきオブジェクトの状態を返します。 -
__setstate__(self, state): 状態からオブジェクトを復元します。
例:
例えば、オブジェクトのすべてのフィールドを保存せず、いくつかを除外したい場合、 __getstate__() メソッドでは以下を行う必要があります:
- 現在のオブジェクトの状態(内部フィールドの
__dict__を使って)を別の変数、 辞書stateにコピーします。 - シリアライズしないフィールドを削除します。
- 生成されたオブジェクトを
__getstate__()関数の結果として返します。
import pickle
class CustomClass:
def __init__(self, value):
self.value = value
self.internal_state = "internal"
def __getstate__(self):
state = self.__dict__.copy()
del state['internal_state'] # 内部状態を除外
return state
def __setstate__(self, state):
self.__dict__.update(state)
self.internal_state = "restored internal" # 内部状態を復元
def __repr__(self):
return f"CustomClass(value={self.value}, internal_state={self.internal_state})"
# オブジェクトの作成
obj = CustomClass(42)
print("オリジナルのオブジェクト:", obj)
# オブジェクトのシリアライズ
serialized_obj = pickle.dumps(obj)
print("シリアライズされたオブジェクト:", serialized_obj)
# オブジェクトのデシリアライズ
deserialized_obj = pickle.loads(serialized_obj)
print("デシリアライズされたオブジェクト:", deserialized_obj)
デシリアライズ時に、__setstate__() 関数内で、私たちは以下の2つのことをします:
-
update()メソッドを使ってオブジェクトの現状を更新します。 - フィールド
internal_state(および他の非シリアライズ可能なフィールド)は 新しい値を取得します。
GO TO FULL VERSION