# 11 `weakref` -- 弱参照

バージョン 2.1 で 新たに追加 された仕様です。

`weakref`モジュールは、Pythonプログラマがオブジェクトへの 弱参照を作成できるようにします。

以下では、用語リファレント (referent) は弱参照が参照するオブジェクトを 意味します。

オブジェクトに対する弱参照は、そのオブジェクトを生かしておくのに 十分な条件にはなりません: あるリファレントに対する参照が弱参照しか 残っていない場合、ガベージコレクション機構は自由にリファレントを破壊し、 そのメモリを別の用途に再利用できます。弱参照の主な用途は、 巨大なオブジェクトを保持するキャッシュやマップ型の実装において、 キャッシュやマップ型にあるという理由だけオブジェクトを存続させたくない 場合です。 例えば、巨大なバイナリ画像のオブジェクトがたくさんあり、 それぞれに名前を関連付けたいとします。 Python の辞書型を使って 名前を画像に対応付けたり画像を名前に対応付けたりすると、 画像オブジェクトは辞書内のキーや値に使われているため存続しつづける ことになります。`weakref` モジュールが提供している `WeakKeyDictionary` や `WeakValueDictionary` クラスは その代用で、対応付けを構築するのに弱参照を使い、キャッシュや マップ型に存在するという理由だけでオブジェクトを存続させないように します。 例えば、もしある画像オブジェクトが `WeakValueDictionary` の 値になっていた場合、最後に残った画像オブジェクトへの参照を 弱参照マップ型が保持していれば、ガーベジコレクションはこのオブジェクトを 再利用でき、画像オブジェクトに対する弱参照内の対応付けはそのまま 削除されます。

`WeakKeyDictionary` や `WeakValueDictionary` は 弱参照を使って実装されていて、キーや値がガーベジコレクションによって回収された ことを弱参照辞書に知らせるような弱参照オブジェクトのコールバック関数を 設定しています。

ほとんどのプログラムが、いずれかの弱参照辞書型を使うだけで必要を満たせるはずです -- 自作の弱参照辞書を直接作成する必要は普通はありません。とはいえ、 弱参照辞書の実装に使われている低水準の機構は、高度な利用を行う際に恩恵を うけられるよう `weakref` モジュールで公開されています。

すべてのオブジェクトを弱参照できるわけではありません。 弱参照できるオブジェクトは、クラスインスタンス、(Cではなく) Pythonで書かれた関数、 (束縛および非束縛の両方の)メソッド、`set` および `frozenset` 型、ファイルオブジェクト、ジェネレータ、型オブジェクト、 `bsddb` モジュールの `DBcursor` 型、ソケット型、 `array`型、`deque`型、および正規表現パターンオブジェクト です。 バージョン 2.4 で 変更 された仕様: ファイル、ソケット、`array`、および正規表現 パターンのサポートを追加しました

`list` や`dict` など、いくつかの組み込み型は弱参照を 直接サポートしませんが、以下のようにサブクラス化を行えばサポートを 追加できます:

    class Dict(dict):
        pass

    obj = Dict(red=1, green=2, blue=3)   # this object is weak referencable

弱参照をサポートするために拡張型を簡単に作れます。 詳細については、5.11.3節 ``拡張型における弱参照''を読んでください。

クラス `ref`( | object[, callback])

  objectへの弱参照を返します。リファレントがまだ生きているならば、 元のオブジェクトは参照オブジェクトの呼び出しで取り出せす。 リファレントがもはや生きていないならば、参照オブジェクトを呼び出したときに `None` を返します。 callback に `None` 以外の値を与えた場合、オブジェクトをまさに後始末処理しようとするときに 呼び出します。このとき弱参照オブジェクトはcallback の唯一のパラメタとして 渡されます。リファレントはもはや利用できません。

  同じオブジェクトに対してたくさんの弱参照を作れます。 それぞれの弱参照に対して登録されたコールバックは、 もっとも新しく登録されたコールバックからもっとも古いものへと呼び出されます。

  コールバックが発生させた例外は標準エラー出力に書き込まれますが、伝搬させられません。 それらはオブジェクトの`__del__()`メソッドが発生させる例外とまったく同様の 方法で処理されます。

  objectがハッシュ可能ならば、弱参照はハッシュ可能です。それらはobjectが 削除された後でもそれらのハッシュ値を保持します。objectが削除されてから初めて `hash()`が呼び出された場合に、その呼び出しは`TypeError`を発生させます。

  弱参照は等価性のテストをサポートしていますが、順序をサポートしていません。 参照がまだ生きているならば、callbackに関係なく二つの参照はそれらの リファレントと同じ等価関係を持ちます。リファレントのどちらか一方が削除された場合、 参照オブジェクトが同じオブジェクトである場合に限り、その参照は等価です。

  バージョン 2.4 で 変更 された仕様: 以前はファクトリでしたが、サブクラス化可能な型になりました。 `object` 型から導出されています

`proxy`( | object[, callback])

  弱参照を使うobjectへのプロキシを返します。弱参照オブジェクトとともに 用いられる明示的な参照外しを要求する代わりに、これはほとんどのコンテキストに おけるプロキシの利用をサポートします。objectが呼び出し可能かどうかに依存して、 返されるオブジェクトは`ProxyType`または`CallableProxyType`のどちらか一方の 型を持ちます。プロキシオブジェクトはリファレントに関係なくハッシュ可能ではありません。 これによって、それらの基本的な変更可能という性質に関係する多くの問題を避けています。 そして、辞書のキーとしてそれらの利用を妨げます。callbackは`ref()`関数の 同じ名前のパラメータと同じものです。

`getweakrefcount`( | object)

  objectを参照する弱参照とプロキシの数を返します。

`getweakrefs`( | object)

  objectを参照するすべての弱参照とプロキシオブジェクトのリストを返します。

クラス `WeakKeyDictionary`( | [dict])

  キーを弱く参照するマッピングクラス。もはやキーへの強い参照がなくなったときに、 辞書のエントリは捨てられます。アプリケーションの他の部分が所有するオブジェクトへ 属性を追加することもなく、それらのオブジェクトに追加データを関連づけるために これを使うことができます。これは属性へのアクセスをオーバーライドするオブジェクトに 特に便利です。

  注意: 注意: `WeakKeyDictionary` は Python 辞書型の上に作られているので、 反復処理を行うときにはサイズ変更してはなりません。`WeakKeyDictionary` の場合、反復処理の最中にプログラムが行った操作が、(ガベージコレクションの副作用として) 「魔法のように」辞書内の要素を消し去ってしまうため、確実なサイズ変更は困難なのです。

クラス `WeakValueDictionary`( | [dict])

  値を弱く参照するマッピングクラス。値への強い参照がもはや存在しなくなったときに、辞書のエントリは捨てられます。

`ReferenceType`
  弱参照オブジェクトのための型オブジェクト。

`ProxyType`
  呼び出し可能でないオブジェクトのプロキシのための型オブジェクト。

`CallableProxyType`
  呼び出し可能なオブジェクトのプロキシのための型オブジェクト。

`ProxyTypes`
  プロキシのためのすべての型オブジェクトを含むシーケンス。これは両方のプロキシ型の名前付けに依存しないで、オブジェクトがプロキシかどうかのテストをより簡単にできます。

exception `ReferenceError`
  プロキシオブジェクトが使われても、元のオブジェクトがガーベジコレクションされてしまっているときに発生する例外。これは標準の`ReferenceError`例外と同じです。

参考:

PEP 0205, Weak References
  この機能の提案と理論的根拠。初期の実装と他の言語における類似の機能についての情報へのリンクを含んでいます。