"weakref" — 弱参照
******************

バージョン 2.1 で追加.

**ソースコード:** Lib/weakref.py

======================================================================

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

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

A weak reference to an object is not enough to keep the object alive:
when the only remaining references to a referent are weak references,
*garbage collection* is free to destroy the referent and reuse its
memory for something else.  A primary use for weak references is to
implement caches or mappings holding large objects, where it’s desired
that a large object not be kept alive solely because it appears in a
cache or mapping.

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

"WeakKeyDictionary" and "WeakValueDictionary" use weak references in
their implementation, setting up callback functions on the weak
references that notify the weak dictionaries when a key or value has
been reclaimed by garbage collection.  Most programs should find that
using one of these weak dictionary types is all they need – it’s not
usually necessary to create your own weak references directly.  The
low-level machinery used by the weak dictionary implementations is
exposed by the "weakref" module for the benefit of advanced uses.

Not all objects can be weakly referenced; those objects which can
include class instances, functions written in Python (but not in C),
methods (both bound and unbound), sets, frozensets, file objects,
*generator*s, type objects, "DBcursor" objects from the "bsddb"
module, sockets, arrays, deques, regular expression pattern objects,
and code objects.

バージョン 2.4 で変更: Added support for files, sockets, arrays, and
patterns.

バージョン 2.7 で変更: thread.lock, threading.Lock, code オブジェクト
のサポートが追加されました。

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

   class Dict(dict):
       pass

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

**CPython implementation detail:** Other built-in types such as
"tuple" and "long" do not support weak references even when
subclassed.

拡張型は、簡単に弱参照をサポートできます。詳細については、 弱参照(Weak
Reference)のサポート を参照してください。

class weakref.ref(object[, callback])

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

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

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

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

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

   バージョン 2.4 で変更: This is now a subclassable type rather than
   a factory function; it derives from "object".

weakref.proxy(object[, callback])

   弱参照を使う *object* へのプロキシを返します。弱参照オブジェクトを
   明示的な参照外しをしながら利用する代わりに、多くのケースでプロキシ
   を利用することができます。返されるオブジェクトは、 *object* が呼び
   出し可能かどうかによって、 "ProxyType" または "CallableProxyType"
   のどちらかの型を持ちます。プロキシオブジェクトはリファレントに関係
   なくハッシュ可能(*hashable*)ではありません。これによって、それらの
   基本的な変更可能という性質による多くの問題を避けています。そして、
   辞書のキーとしての利用を妨げます。 *callback* は "ref()" 関数の同じ
   名前のパラメータと同じものです。(— 訳注: リファレントが変更不能型で
   あっても、プロキシはリファレントが消えるという状態の変更があるため
   に、変更可能型です。—)

weakref.getweakrefcount(object)

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

weakref.getweakrefs(object)

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

class weakref.WeakKeyDictionary([dict])

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

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

"WeakKeyDictionary" objects have the following additional methods.
These expose the internal references directly.  The references are not
guaranteed to be 「live」 at the time they are used, so the result of
calling the references needs to be checked before being used.  This
can be used to avoid creating references that will cause the garbage
collector to keep the keys around longer than needed.

WeakKeyDictionary.iterkeyrefs()

   キーへの弱参照を持つ iterable オブジェクトを返します。

   バージョン 2.5 で追加.

WeakKeyDictionary.keyrefs()

   Return a list of weak references to the keys.

   バージョン 2.5 で追加.

class weakref.WeakValueDictionary([dict])

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

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

"WeakValueDictionary" objects have the following additional methods.
These methods have the same issues as the "iterkeyrefs()" and
"keyrefs()" methods of "WeakKeyDictionary" objects.

WeakValueDictionary.itervaluerefs()

   値への弱参照を持つ iterable オブジェクトを返します。

   バージョン 2.5 で追加.

WeakValueDictionary.valuerefs()

   Return a list of weak references to the values.

   バージョン 2.5 で追加.

class weakref.WeakSet([elements])

   要素への弱参照を持つ集合型。要素への強参照が無くなったときに、その
   要素は削除されます。

   バージョン 2.7 で追加.

weakref.ReferenceType

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

weakref.ProxyType

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

weakref.CallableProxyType

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

weakref.ProxyTypes

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

exception weakref.ReferenceError

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

参考:

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


弱参照オブジェクト
==================

Weak reference objects have no attributes or methods, but do allow the
referent to be obtained, if it still exists, by calling it:

>>> import weakref
>>> class Object:
...     pass
...
>>> o = Object()
>>> r = weakref.ref(o)
>>> o2 = r()
>>> o is o2
True

リファレントがもはや存在しないならば、参照オブジェクトの呼び出しは
"None" を返します:

>>> del o, o2
>>> print r()
None

弱参照オブジェクトがまだ生きているかどうかのテストは、式 "ref() is not
None" を用いて行われます。通常、参照オブジェクトを使う必要があるアプリ
ケーションコードはこのパターンに従います:

   # r is a weak reference object
   o = r()
   if o is None:
       # referent has been garbage collected
       print "Object has been deallocated; can't frobnicate."
   else:
       print "Object is still live!"
       o.do_something_useful()

「生存性(liveness)」のテストを分割すると、スレッド化されたアプリケーシ
ョンにおいて競合状態を作り出します。 (訳注:"if r() is not None:
r().do_something()" では、2度目のr()がNoneを返す可能性があります) 弱参
照が呼び出される前に、他のスレッドは弱参照が無効になる原因となり得ます
。上で示したイディオムは、シングルスレッドのアプリケーションと同じくマ
ルチスレッド化されたアプリケーションにおいても安全です。

サブクラス化を行えば、 "ref" オブジェクトの特殊なバージョンを作成でき
ます。これは "WeakValueDictionary" の実装で使われており、マップ内の各
エントリによるメモリのオーバヘッドを減らしています。こうした実装は、あ
る参照に追加情報を関連付けたい場合に便利ですし、リファレントを取り出す
ための呼び出し時に何らかの追加処理を行いたい場合にも使えます。

以下の例では、 "ref" のサブクラスを使って、あるオブジェクトに追加情報
を保存し、リファレントがアクセスされたときにその値に作用をできるように
するための方法を示しています:

   import weakref

   class ExtendedRef(weakref.ref):
       def __init__(self, ob, callback=None, **annotations):
           super(ExtendedRef, self).__init__(ob, callback)
           self.__counter = 0
           for k, v in annotations.iteritems():
               setattr(self, k, v)

       def __call__(self):
           """Return a pair containing the referent and the number of
           times the reference has been called.
           """
           ob = super(ExtendedRef, self).__call__()
           if ob is not None:
               self.__counter += 1
               ob = (ob, self.__counter)
           return ob


使用例
======

この簡単な例では、アプリケーションが以前に参照したオブジェクトを取り出
すためにオブジェクトIDを利用する方法を示します。オブジェクトに生きたま
まであることを強制することなく、オブジェクトの IDを他のデータ構造の中
で使うことができ、必要に応じてIDからオブジェクトを取り出せます。

   import weakref

   _id2obj_dict = weakref.WeakValueDictionary()

   def remember(obj):
       oid = id(obj)
       _id2obj_dict[oid] = obj
       return oid

   def id2obj(oid):
       return _id2obj_dict[oid]
