"weakref" --- Weak references
*****************************

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

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

The "weakref" module allows the Python programmer to create *weak
references* to objects.

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

オブジェクトへの弱参照があることは、そのオブジェクトを生かしておくのに
は不十分です。リファレントへの参照が弱参照しか残っていない場合、
*garbage collection* はリファレントを自由に破棄し、メモリを別のものに
再利用することができます。しかし、オブジェクトへの強参照がなくても、オ
ブジェクトが実際に破棄されるまでは、弱参照はオブジェクトを返す場合があ
ります。

弱参照の主な用途は、巨大なオブジェクトを保持するキャッシュやマッピング
を実装することです。ここで、キャッシュやマッピングに保持されているから
という理由だけで、巨大なオブジェクトが生き続けることは望ましくありませ
ん。

For example, if you have a number of large binary image objects, you
may wish to associate a name with each.  If you used a Python
dictionary to map names to images, or images to names, the image
objects would remain alive just because they appeared as values or
keys in the dictionaries.  The "WeakKeyDictionary" and
"WeakValueDictionary" classes supplied by the "weakref" module are an
alternative, using weak references to construct mappings that don't
keep objects alive solely because they appear in the mapping objects.
If, for example, an image object is a value in a
"WeakValueDictionary", then when the last remaining references to that
image object are the weak references held by weak mappings, garbage
collection can reclaim the object, and its corresponding entries in
weak mappings are simply deleted.

"WeakKeyDictionary" と "WeakValueDictionary" はその実装に弱参照を使用
しており、キーや値がガーベジコレクションによって回収されたことを弱参照
辞書に通知するコールバック関数を設定しています。 "WeakSet" は "set" イ
ンターフェースを実装していますが、 "WeakKeyDictionary" のように要素へ
の弱参照を持ちます。

"finalize" は、オブジェクトのガベージコレクションの実行時にクリーンア
ップ関数が呼び出されるように登録する、単純な方法を提供します。これは、
未加工の弱参照上にコールバック関数を設定するよりも簡単です。なぜなら、
オブジェクトのコレクションが完了するまでファイナライザが生き続けること
を、モジュールが自動的に保証するからです。

Most programs should find that using one of these weak container types
or "finalize" is all they need -- it's not usually necessary to create
your own weak references directly.  The low-level machinery is exposed
by the "weakref" module for the benefit of advanced uses.

全てのオブジェクトが弱参照で参照できるわけではありません。弱参照をサポ
ートするオブジェクトは、クラスインスタンス、(C ではなく) Python で書か
れた関数、インスタンスメソッド、set オブジェクト、frozenset オブジェク
ト、 *file オブジェクト* 、 *generators* 型のオブジェクト、socket オブ
ジェクト、array オジェクト、deque オブジェクト、正規表現パターンオブジ
ェクト、code オブジェクトです。

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

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

   class Dict(dict):
       pass

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

"tuple" や "int" など、他の組み込み型はサブクラス化しても弱参照をサポ
ートしません。

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

When "__slots__" are defined for a given type, weak reference support
is disabled unless a "'__weakref__'" string is also present in the
sequence of strings in the "__slots__" declaration. See __slots__
documentation for details.

class weakref.ref(object[, callback])

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

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

   Exceptions raised by the callback will be noted on the standard
   error output, but cannot be propagated; they are handled in exactly
   the same way as exceptions raised from an object's "__del__()"
   method.

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

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

   これはサブクラス化可能な型というよりファクトリ関数です。

   Weak references are generic over the type of the object they
   reference.

   __callback__

      この読み出し専用の属性は、現在弱参照に関連付けられているコールバ
      ックを返します。コールバックが存在しないか、弱参照のリファレント
      が生きていない場合、この属性の値は "None"  になります。

   バージョン 3.4 で変更: "__callback__" 属性が追加されました。

weakref.proxy(object[, callback])

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

   Accessing an attribute of the proxy object after the referent is
   garbage collected raises "ReferenceError".

   バージョン 3.8 で変更: Extended the operator support on proxy
   objects to include the matrix multiplication operators "@" and
   "@=".

weakref.getweakrefcount(object)

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

weakref.getweakrefs(object)

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

class weakref.WeakKeyDictionary([dict])

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

   Note that when a key with equal value to an existing key (but not
   equal identity) is inserted into the dictionary, it replaces the
   value but does not replace the existing key. Due to this, when the
   reference to the original key is deleted, it also deletes the entry
   in the dictionary:

      >>> class T(str): pass
      ...
      >>> k1, k2 = T(), T()
      >>> d = weakref.WeakKeyDictionary()
      >>> d[k1] = 1   # d = {k1: 1}
      >>> d[k2] = 2   # d = {k1: 2}
      >>> del k1      # d = {}

   A workaround would be to remove the key prior to reassignment:

      >>> class T(str): pass
      ...
      >>> k1, k2 = T(), T()
      >>> d = weakref.WeakKeyDictionary()
      >>> d[k1] = 1   # d = {k1: 1}
      >>> del d[k1]
      >>> d[k2] = 2   # d = {k2: 2}
      >>> del k1      # d = {k2: 2}

   バージョン 3.9 で変更: **PEP 584** で規定されている "|" 演算子と
   "|=" 演算子のサポートを追加しました。

"WeakKeyDictionary" オブジェクトは、追加のメソッドを持ちます。このメソ
ッドは、内部の参照を直接公開します。その参照は、利用される時に生存して
いるとは限りません。なので、参照を利用する前に、その参照をチェックする
必要があります。これにより、必要なくなったキーの参照が残っているために
、ガベージコレクタがそのキーを削除できなくなる事態を避ける事ができます
。

WeakKeyDictionary.keyrefs()

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

class weakref.WeakValueDictionary([dict])

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

   バージョン 3.9 で変更: **PEP 584** で規定されている "|" 演算子と
   "|=" 演算子のサポートを追加しました。

"WeakValueDictionary" objects have an additional method that has the
same issues as the "WeakKeyDictionary.keyrefs()" method.

WeakValueDictionary.valuerefs()

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

class weakref.WeakSet([elements])

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

class weakref.WeakMethod(method[, callback])

   拡張された "ref" のサブクラスで、束縛されたメソッドへの弱参照をシミ
   ュレートします (つまり、クラスで定義され、インスタンスにあるメソッ
   ド)。 束縛されたメソッドは短命なので、標準の弱参照では保持し続けら
   れません。 "WeakMethod" には、オブジェクトと元々の関数が死ぬまで束
   縛されたメソッドを再作成する特別なコードがあります:

      >>> class C:
      ...     def method(self):
      ...         print("method called!")
      ...
      >>> c = C()
      >>> r = weakref.ref(c.method)
      >>> r()
      >>> r = weakref.WeakMethod(c.method)
      >>> r()
      <bound method C.method of <__main__.C object at 0x7fc859830220>>
      >>> r()()
      method called!
      >>> del c
      >>> gc.collect()
      0
      >>> r()
      >>>

   *callback* is the same as the parameter of the same name to the
   "ref()" function.

   Added in version 3.4.

class weakref.finalize(obj, func, /, *args, **kwargs)

   *obj* がガベージコレクションで回収されるときに呼び出される、呼び出
   し可能なファイナライザオブジェクトを返します。 通常の弱参照とは異な
   り、ファイナライザは参照しているオブジェクトが回収されるまで必ず生
   き残り、そのおかげでライフサイクル管理が大いに簡単になります。

   ファイナライザは (直接もしくはガベージコレクションのときに) 呼び出
   されるまで *生きている* と見なされ、呼び出された後には *死んでいま
   す* 。 生きているファイナライザを呼び出すと、 "func(*arg,
   **kwargs)" を評価した結果を返します。一方、死んでいるファイナライザ
   を呼び出すと "None" を返します。

   Exceptions raised by finalizer callbacks during garbage collection
   will be shown on the standard error output, but cannot be
   propagated.  They are handled in the same way as exceptions raised
   from an object's "__del__()" method or a weak reference's callback.

   プログラムが終了するとき、生き残ったそれぞれのファイナライザは、自
   身の "atexit" 属性が偽に設定されるまで呼び出され続けます。 ファイナ
   ライザは生成された順序の逆順で呼び出されます。

   A finalizer will never invoke its callback during the later part of
   the *interpreter shutdown* when module globals are liable to have
   been replaced by "None".

   __call__()

      If *self* is alive then mark it as dead and return the result of
      calling "func(*args, **kwargs)".  If *self* is dead then return
      "None".

   detach()

      If *self* is alive then mark it as dead and return the tuple
      "(obj, func, args, kwargs)".  If *self* is dead then return
      "None".

   peek()

      If *self* is alive then return the tuple "(obj, func, args,
      kwargs)".  If *self* is dead then return "None".

   alive

      ファイナライザが生きている場合には真、そうでない場合には偽のプロ
      パティです。

   atexit

      A writable boolean property which by default is true.  When the
      program exits, it calls all remaining live finalizers for which
      "atexit" is true.  They are called in reverse order of creation.

   注釈:

     It is important to ensure that *func*, *args* and *kwargs* do not
     own any references to *obj*, either directly or indirectly, since
     otherwise *obj* will never be garbage collected.  In particular,
     *func* should not be a bound method of *obj*.

   Added in version 3.4.

class weakref.ReferenceType

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

class weakref.ProxyType

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

class weakref.CallableProxyType

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

weakref.ProxyTypes

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

参考:

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


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

Weak reference objects have no methods and no attributes besides
"ref.__callback__". A weak reference object allows 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().__init__(ob, callback)
           self.__counter = 0
           for k, v in annotations.items():
               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().__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]


ファイナライザオブジェクト
==========================

The main benefit of using "finalize" is that it makes it simple to
register a callback without needing to preserve the returned finalizer
object.  For instance

>>> import weakref
>>> class Object:
...     pass
...
>>> kenny = Object()
>>> weakref.finalize(kenny, print, "You killed Kenny!")
<finalize object at ...; for 'Object' at ...>
>>> del kenny
You killed Kenny!

ファイナライザは直接呼び出すこともできます。ただし、ファイナライザはコ
ールバックを最大でも一度しか呼び出しません。

>>> def callback(x, y, z):
...     print("CALLBACK")
...     return x + y + z
...
>>> obj = Object()
>>> f = weakref.finalize(obj, callback, 1, 2, z=3)
>>> assert f.alive
>>> assert f() == 6
CALLBACK
>>> assert not f.alive
>>> f()                     # callback not called because finalizer dead
>>> del obj                 # callback not called because finalizer dead

You can unregister a finalizer using its "detach()" method.  This
kills the finalizer and returns the arguments passed to the
constructor when it was created.

>>> obj = Object()
>>> f = weakref.finalize(obj, callback, 1, 2, z=3)
>>> f.detach()
(<...Object object ...>, <function callback ...>, (1, 2), {'z': 3})
>>> newobj, func, args, kwargs = _
>>> assert not f.alive
>>> assert newobj is obj
>>> assert func(*args, **kwargs) == 6
CALLBACK

Unless you set the "atexit" attribute to "False", a finalizer will be
called when the program exits if it is still alive.  For instance

   >>> obj = Object()
   >>> weakref.finalize(obj, print, "obj dead or exiting")
   <finalize object at ...; for 'Object' at ...>
   >>> exit()
   obj dead or exiting


Comparing finalizers with "__del__()" methods
=============================================

インスタンスが一時ディレクトリを表す、クラスを作成するとします。そのデ
ィレクトリは、次のイベントのいずれかが起きた時に、そのディレクトリの内
容とともに削除されるべきです。

* オブジェクトのガベージコレクションが行われた場合

* the object's "remove()" method is called, or

* プログラムが終了した場合

We might try to implement the class using a "__del__()" method as
follows:

   class TempDir:
       def __init__(self):
           self.name = tempfile.mkdtemp()

       def remove(self):
           if self.name is not None:
               shutil.rmtree(self.name)
               self.name = None

       @property
       def removed(self):
           return self.name is None

       def __del__(self):
           self.remove()

Starting with Python 3.4, "__del__()" methods no longer prevent
reference cycles from being garbage collected, and module globals are
no longer forced to "None" during *interpreter shutdown*. So this code
should work without any issues on CPython.

However, handling of "__del__()" methods is notoriously implementation
specific, since it depends on internal details of the interpreter's
garbage collector implementation.

A more robust alternative can be to define a finalizer which only
references the specific functions and objects that it needs, rather
than having access to the full state of the object:

   class TempDir:
       def __init__(self):
           self.name = tempfile.mkdtemp()
           self._finalizer = weakref.finalize(self, shutil.rmtree, self.name)

       def remove(self):
           self._finalizer()

       @property
       def removed(self):
           return not self._finalizer.alive

Defined like this, our finalizer only receives a reference to the
details it needs to clean up the directory appropriately. If the
object never gets garbage collected the finalizer will still be called
at exit.

The other advantage of weakref based finalizers is that they can be
used to register finalizers for classes where the definition is
controlled by a third party, such as running code when a module is
unloaded:

   import weakref, sys
   def unloading_module():
       # implicit reference to the module globals from the function body
   weakref.finalize(sys.modules[__name__], unloading_module)

注釈:

  If you create a finalizer object in a daemonic thread just as the
  program exits then there is the possibility that the finalizer does
  not get called at exit.  However, in a daemonic thread
  "atexit.register()", "try: ... finally: ..." and "with: ..." do not
  guarantee that cleanup occurs either.
