pickleは、ファイルなどに保存するために、Python オブジェクトをバイト列にシリアライズするための標準ライブラリです。Pickle可能なオブジェクトはpickable、シリアライズされたバイト列からオブジェクトを再生成することをUnpickleと呼んでいます。
Pickleは、デフォルトでは__dict__
に登録されているオブジェクトの属性をシリアライズしようとしますが、pickle用のスペシャルメソッドを定義することにより、その挙動をカスタマイズすることができます。特に、pickleするオブジェクトが、pickle出来ないオブジェクトをメンバーとして持っている場合や、そのオブジェクトが引数をとるコンストラクタで生成される場合などに使用します。
メソッド | 使用目的 |
---|---|
__getnewargs__() |
Unpickleする際にコンストラクタに渡す引数を指定する。 |
__getstate__() |
__dict__ ではなく、このメソッドが返すオブジェクトをpickleする。 |
__setstate__(state) |
pickleされていたオブジェクトをstateとして受け取り、unpickle時の処理を行う。 |
次のコードはこれらのメソッドの挙動を確認するためサンプルスクリプトです。
import pickle
class Foo:
def __new__(self, a):
print('in __new__:', a)
self = object.__new__(self)
# self.a = a
return self
def __init__(self, a):
print('in __init__:', a)
self.a = a
def __getstate__(self):
print('in __getstate__:', self.a)
state = self.__dict__.copy()
return state
def __getnewargs__(self):
print('in __getnewargs__:', self.a)
return (2 * self.a,)
def __setstate__(self, state):
self.__dict__.update(state)
print('in __setstate__:', self.a)
foo = Foo(3)
bar = pickle.dumps(foo)
baz = pickle.loads(bar)
print(baz.__dict__)
このスクリプトの実行結果は次のようになります。
in __new__: 3
in __init__: 3
in __getnewargs__: 3
in __getstate__: 3
in __new__: 6
in __setstate__: 3
{'a': 3}
pickleのマニュアルに書いてあるとおりですが、下記のことが分かります。
-
__getnewargs__
は、Pickleする時に呼ばれる。つまり、Unpickleされるときに__new__
に渡す引数の情報は、Pickleされている。 -
__new__
には、__getnewargs__
が返した値が渡されている。 - Unpicleでは
__init__
は呼ばれない。