\section{\module{weakref} ---
         弱参照}

\declaremodule{extension}{weakref}
\modulesynopsis{弱参照と弱辞書のサポート。}
\moduleauthor{Fred L. Drake, Jr.}{fdrake@acm.org}
\moduleauthor{Neil Schemenauer}{nas@arctrix.com}
\moduleauthor{Martin von L\"owis}{martin@loewis.home.cs.tu-berlin.de}
\sectionauthor{Fred L. Drake, Jr.}{fdrake@acm.org}

\versionadded{2.1}


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

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

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

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

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

すべてのオブジェクトを弱参照できるわけではありません。
弱参照できるオブジェクトは、クラスインスタンス、(Cではなく) Pythonで書かれた関数、
(束縛および非束縛の両方の)メソッド、\class{set} および 
\class{frozenset} 型、ファイルオブジェクト、ジェネレータ、型オブジェクト、
\module{bsddb} モジュールの \class{DBcursor} 型、ソケット型、
\class{array}型、\class{deque}型、および正規表現パターンオブジェクト
です。
\versionchanged[ファイル、ソケット、\class{array}、および正規表現
パターンのサポートを追加しました]{2.4}
 
\class{list} や\class{dict} など、いくつかの組み込み型は弱参照を
直接サポートしませんが、以下のようにサブクラス化を行えばサポートを
追加できます:

\begin{verbatim}
class Dict(dict):
    pass

obj = Dict(red=1, green=2, blue=3)   # this object is weak referencable
\end{verbatim}


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


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

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

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

\var{object}がハッシュ可能ならば、弱参照はハッシュ可能です。それらは\var{object}が
削除された後でもそれらのハッシュ値を保持します。\var{object}が削除されてから初めて
\function{hash()}が呼び出された場合に、その呼び出しは\exception{TypeError}を発生させます。
  
弱参照は等価性のテストをサポートしていますが、順序をサポートしていません。
参照がまだ生きているならば、\var{callback}に関係なく二つの参照はそれらの
リファレントと同じ等価関係を持ちます。リファレントのどちらか一方が削除された場合、
参照オブジェクトが同じオブジェクトである場合に限り、その参照は等価です。

\versionchanged[以前はファクトリでしたが、サブクラス化可能な型になりました。
  \class{object} 型から導出されています]{2.4}

\end{classdesc}

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

\begin{funcdesc}{getweakrefcount}{object}
  \var{object}を参照する弱参照とプロキシの数を返します。
\end{funcdesc}

\begin{funcdesc}{getweakrefs}{object}
  \var{object}を参照するすべての弱参照とプロキシオブジェクトのリストを返します。
\end{funcdesc}

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

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

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

\begin{datadesc}{ReferenceType}
  弱参照オブジェクトのための型オブジェクト。
\end{datadesc}

\begin{datadesc}{ProxyType}
  呼び出し可能でないオブジェクトのプロキシのための型オブジェクト。
\end{datadesc}

\begin{datadesc}{CallableProxyType}
  呼び出し可能なオブジェクトのプロキシのための型オブジェクト。
\end{datadesc}

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

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


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


\subsection{弱参照オブジェクト
            \label{weakref-objects}}

弱参照オブジェクトは属性あるいはメソッドを持ちません。しかし、リファレントがまだ存在するならば、呼び出すことでそのリファレントを取得できるようにします:

\begin{verbatim}
>>> import weakref
>>> class Object:
...     pass
...
>>> o = Object()
>>> r = weakref.ref(o)
>>> o2 = r()
>>> o is o2
True
\end{verbatim}

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

\begin{verbatim}
>>> del o, o2
>>> print r()
None
\end{verbatim}

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

\begin{verbatim}
# rは弱参照オブジェクト
o = r()
if o is None:
    # リファレントがガーベジコレクトされた
    print "Object has been allocated; can't frobnicate."
else:
    print "Object is still live!"
    o.do_something_useful()
\end{verbatim}

``生存性(liveness)''のテストを個々に行うと、スレッド化されたアプリケーションにおいて競合状態を作り出します。弱参照が呼び出される前に、他のスレッドは弱参照が無効になる原因となり得ます。上で示したイディオムは、シングルスレッド化されたアプリケーションと同じくスレッド化されたアプリケーションにおいて安全です。

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

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

\begin{verbatim}
import weakref

class ExtendedRef(weakref.ref):
    def __new__(cls, ob, callback=None, **annotations):
        weakref.ref.__new__(cls, ob, callback)
        self.__counter = 0

    def __init__(self, ob, callback=None, **annotations):
        super(ExtendedRef, self).__init__(ob, callback)
        for k, v in annotations:
            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)()
        if ob is not None:
            self.__counter += 1
            ob = (ob, self.__counter)
        return ob
\end{verbatim}



\subsection{例\label{weakref-example}}

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

% Example contributed by Tim Peters 
\begin{verbatim}
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]
\end{verbatim}


\subsection{拡張型における弱参照
            \label{weakref-extension}}

実装の目的の一つは、弱参照によって恩恵を受けない数のような型のオブジェクトにオーバーヘッドを負わせることなく、どんな型でも弱参照メカニズムに加わることができるようにすることです。

弱く参照可能なオブジェクトに対して、弱参照メカニズムを使うために、拡張は\ctype{PyObject*}フィールドをインスタンス構造に含んでいなければなりません。オブジェクトのコンストラクタによって、それは\NULL{} に初期化しなければなりません。対応する型オブジェクトの\member{tp_weaklistoffset}フィールドをフィールドのオフセットに設定することもしなければなりません。また、\constant{Py_TPFLAGS_HAVE_WEAKREFS}をtp_flagsスロットへ追加する必要もあります。例えば、インスタンス型は次のような構造に定義されます:

\begin{verbatim}
typedef struct {
    PyObject_HEAD
    PyClassObject *in_class;       /* クラスオブジェクト */
    PyObject      *in_dict;        /* 辞書 */
    PyObject      *in_weakreflist; /* 弱参照のリスト */
} PyInstanceObject;
\end{verbatim}

インスタンスに対して静的に宣言される型オブジェクトはこのように定義されます:

\begin{verbatim}
PyTypeObject PyInstance_Type = {
    PyObject_HEAD_INIT(&PyType_Type)
    0,
    "module.instance",

    /* 簡単のためにたくさんのものを省略... */

    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS   /* tp_flags */
    0,                                          /* tp_doc */
    0,                                          /* tp_traverse */
    0,                                          /* tp_clear */
    0,                                          /* tp_richcompare */
    offsetof(PyInstanceObject, in_weakreflist), /* tp_weaklistoffset */
};
\end{verbatim}

型コンストラクタは弱参照リストを\NULL に初期化する責任があります:

\begin{verbatim}
static PyObject *
instance_new() {
    /* 簡単のために他の初期化を省略 */

    self->in_weakreflist = NULL;

    return (PyObject *) self;
} 
\end{verbatim}

さらに一つだけ追加すると、どんな弱参照でも取り除くためには、デストラクタは弱参照マネージャを呼び出す必要があります。オブジェクトの破壊のどんな他の部分が起きる前にこれを行うべきですが、弱参照リストが非\NULL である場合はこれが要求されるだけです:

\begin{verbatim}
static void
instance_dealloc(PyInstanceObject *inst)
{
    /* 必要なら一時オブジェクトを割り当ててください。
       しかし、まだ破壊しないでください。
     */

    if (inst->in_weakreflist != NULL)
        PyObject_ClearWeakRefs((PyObject *) inst);

    /* 普通にオブジェクトの破壊を進めてください。 */
}
\end{verbatim}
