### 2 拡張型の pickle 化および unpickle 化

`Pickler` が全く未知の型の -- 拡張型のような -- オブジェクトに 遭遇した場合、pickle 化方法のヒントとして 2 個所を探します。 第一は `__reduce__()` メソッドを実装しているかどうかです。 もし実装されていれば、pickle 化時に `__reduce__()` メソッド が引数なしで呼び出されます。メソッドはこの呼び出しに対して 文字列またはタプルのどちらかを返さねばなりません。

文字列を返す場合、その文字列は通常通りに pickle 化されるグローバル変数 の名前を指しています。`__reduce__` の返す文字列は、 モジュールにからみてオブジェクトのローカルな名前でなければなりません; pickle モジュールはモジュールの名前空間を検索して、オブジェクトの 属するモジュールを決定します。

タプルを返す場合、タプルの要素数は 2 から 5 でなければなりません。 オプションの要素は省略したり `None` を指定したりできます。 各要素の意味づけは以下の通りです:

- 呼び出し可能なオブジェクトで、unpickle 化環境において、クラスか、 ``安全なコンストラクタ (safe constructor)'' (下を参照してください) として登録 されているか、属性 `__safe_for_unpickling__` を持ち値が真に 設定されているような呼び出し可能なオブジェクトでなければなりません。 そうでない場合、 unpickle 化環境で `UnpicklingError` が 送出されます。通常通り、呼び出しオブジェクト自体はその名前が pickle 化されます。

- オブジェクトの初期バージョンを生成するために呼び出される 呼び出し可能オブジェクトです。この呼び出し可能オブジェクトへの引数 はタプルの次の要素で与えられます。それ以降の要素では pickle 化されたデータを完全に再構築するために使われる付加的な状態情報 が与えられます。

  逆 pickle 化の環境下では、このオブジェクトはクラスか、 ``安全なコンストラクタ (safe constructor, 下記参照)'' として登録 されていたり属性`__safe_for_unpickling__` の値が真であるような 呼び出し可能オブジェクトでなければなりません。 そうでない場合、逆 pickle 化を行う環境で`UnpicklingError` が送出されます。通常通り、 callable は名前だけで pickle 化されるので 注意してください。

- 呼び出し可能なオブジェクトのための引数からなるタプルか、あるいは `None`
  リリース 2.3 で撤廃されました。 引数のタプルを使ってください

  。

  リリース 2.3 で撤廃されました。 この要素が`None` の場合、呼び出し可能オブジェクトを 直接呼び出す代わりに、`__basicnew__()` メソッドを引数なしで 呼び出します; このメソッドは逆 pickle 化されたオブジェクトも返さねば なりません。とはいえ、`None` の指定は撤廃されました。 引数からなるタプルを返すようにしてください。

- オプションとして、オブジェクトの状態。 3.14.5 節で記述されているようにして、オブジェクトの `__setstate__()` メソッドに渡されます。オブジェクトが `__setstate__()` メソッドを持たない場合、上記のように、 この値は辞書でなくてはならず、オブジェクトの `__dict__` に追加されます。

- オプションとして、リスト中の連続する要素を返すイテレータ (シーケンスではありません)。このリストの要素は pickle 化され、 `obj.append(item)` または `obj.extend(list_of_items)` のいずれかを使って追加されます。主にリストのサブクラスで用いられて いますが、他のクラスでも、適切なシグネチャの `append()` や `extend()` を備えている限り利用できます。 (`append()` と`extend()` のいずれを使うかは、 どのバージョンの pickle プロトコルを使っているか、そして追加する 要素の数で決まります。従って両方のメソッドをサポートしていなければ なりません。)

- オプションとして、辞書中の連続する要素を返すイテレータ (シーケンスではありません)。このリストの要素は `(key, value)` という形式でなければなりません。要素は pickle 化され、 `obj[key] = value` を使ってオブジェクトに格納 されます。主に辞書のサブクラスで用いられていますが、他のクラスでも、 `__setitem__` を備えている限り利用できます。

リリース 2.3 で撤廃されました。 引数のタプルを使ってください。

`__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 化については ``安全なコンストラクタ'' であると考えられます。