Pickler が全く未知の型の -- 拡張型のような -- オブジェクトに 遭遇した場合、pickle 化方法のヒントとして 2 個所を探します。 第一は __reduce__() メソッドを実装しているかどうかです。 もし実装されていれば、pickle 化時に __reduce__() メソッド が引数なしで呼び出されます。メソッドはこの呼び出しに対して 文字列またはタプルのどちらかを返さねばなりません。
文字列を返す場合、その文字列は通常通りに pickle 化されるグローバル変数 の名前を指しています。__reduce__ の返す文字列は、 モジュールにからみてオブジェクトのローカルな名前でなければなりません; pickle モジュールはモジュールの名前空間を検索して、オブジェクトの 属するモジュールを決定します。
タプルを返す場合、タプルの要素数は 2 から 5 でなければなりません。
オプションの要素は省略したり None
を指定したりできます。
各要素の意味づけは以下の通りです:
逆 pickle 化の環境下では、このオブジェクトはクラスか、 ``安全なコンストラクタ (safe constructor, 下記参照)'' として登録 されていたり属性__safe_for_unpickling__ の値が真であるような 呼び出し可能オブジェクトでなければなりません。 そうでない場合、逆 pickle 化を行う環境でUnpicklingError が送出されます。通常通り、 callable は名前だけで pickle 化されるので 注意してください。
None
None
の場合、呼び出し可能オブジェクトを
直接呼び出す代わりに、__basicnew__() メソッドを引数なしで
呼び出します; このメソッドは逆 pickle 化されたオブジェクトも返さねば
なりません。とはいえ、None
の指定は撤廃されました。
引数からなるタプルを返すようにしてください。
obj.append(item)
または obj.extend(list_of_items)
のいずれかを使って追加されます。主にリストのサブクラスで用いられて
いますが、他のクラスでも、適切なシグネチャの append() や
extend() を備えている限り利用できます。
(append() とextend() のいずれを使うかは、
どのバージョンの pickle プロトコルを使っているか、そして追加する
要素の数で決まります。従って両方のメソッドをサポートしていなければ
なりません。)
(key, value)
という形式でなければなりません。要素は pickle 化され、
obj[key] = value
を使ってオブジェクトに格納
されます。主に辞書のサブクラスで用いられていますが、他のクラスでも、
__setitem__ を備えている限り利用できます。
__reduce__ を実装する場合、プロトコルのバージョンを 知っておくと便利なことがあります。これは __reduce__ の 代わりに__reduce_ex__ を使って実現できます。 __reduce_ex__ が定義されている場合、 __reduce__ よりも優先して呼び出されます (以前のバージョンとの互換性のために __reduce__ を残しておいてもかまいません)。 __reduce_ex__ はプロトコルのバージョンを表す 整数の引数を一つ伴って呼び出されます。
object クラスでは __reduce__ と __reduce_ex__ の両方を定義しています。とはいえ、 サブクラスで __reduce__ をオーバライドしており、 __reduce_ex__ をオーバライドしていない場合には、 __reduce_ex__ の実装がそれを検出して __reduce__ を呼び出すようになっています。
pickle 化するオブジェクト上で __reduce__() メソッドを実装 する代わりに、copy_reg モジュールを使って 呼び出し可能オブジェクトを登録する方法もあります。このモジュール はプログラムに ``縮小化関数 (reduction function)'' と ユーザ定義型のためのコンストラクタを登録する方法を提供します。 縮小化関数は、単一の引数として pickle 化するオブジェクトをとる ことを除き、上で述べた __reduce__() メソッドと同じ意味 とインタフェースを持ちます。
登録されたコンストラクタは上で述べたような unpickle 化については ``安全なコンストラクタ'' であると考えられます。
ご意見やご指摘をお寄せになりたい方は、 このドキュメントについて... をご覧ください。