Python PR

【Python】参照先のオブジェクトが削除されると消える参照【弱参照】

記事内に商品プロモーションを含む場合があります

この記事では、Pythonで弱参照を使う方法を解説します。

弱参照とは、ガベージコレクタから参照していると思われない参照のことを言います。

オブジェクトの参照が弱参照のみになった場合、そのオブジェクトは削除してもよいオブジェクトとしてガベージコレクタに認識されます。

それでは、弱参照の使い方を見ていきましょう!

弱参照の使い方

弱参照は、weakrefモジュールを使うことで簡単に扱うことができます。weakrefモジュールは、標準ライブラリなのでインポートするだけで使用可能です。

import weakref

弱参照をサポートしている型は、ユーザー定義型かサブクラス化したリストや辞書です。

# ユーザー定義型
class クラス名:
    pass

# 辞書のサブクラス
class Dict(dict):
    pass

オブジェクトの弱参照を返すにはweakref.ref(object[, callback])を使います。

import weakref

# 簡単なクラス
class MyClass:
    def __init__(self, value):
        self.value = value

# インスタンス化
mc = MyClass('mcです')

# 弱参照の生成
ref = weakref.ref(mc)
print(ref().value)

# 参照元のオブジェクト削除
del mc

print(ref().value)

実行結果

mcです
Traceback (most recent call last):
  File "main.py", line 18, in 
    print(ref().value)
AttributeError: 'NoneType' object has no attribute 'value'

weakref.ref()は、参照を返しているので呼び出すには()が必要となります。

callback引数に関数を指定することでオブジェクトが削除された時に指定した関数を呼び出すことができます。指定した関数の引数には、その弱参照オブジェクトが渡されます。

import weakref

class MyClass:
    pass

mc = MyClass()
# callbackを指定
ref = weakref.ref(mc, print)

print('del 開始')
del mc
print('del 終了')

実行結果

del 開始
<weakref at 0x7fa450a299f0; dead>
del 終了

弱参照オブジェクトは、参照先が消えている場合にNoneを返します。

import weakref

class MyClass:
    pass

mc = MyClass()
ref = weakref.ref(mc)

del mc

if ref():
    print('参照先が存在します')
else:
    print('参照先が存在しません')

実行結果

参照先が存在しません

key・valueを弱参照する辞書

辞書のkeyを弱参照するにはWeakKeyDictionary([dict])valueを弱参照とするにはWeakValueDictionary([dict])を使います。

WeakKeyDictionary([dict]) key を弱参照する辞書
WeakValueDictionary([dict]) value を弱参照する辞書

以下のコードは、WeakValueDictionary([dict])を使ってvalueを弱参照しただけです。

import weakref

# 簡単なクラス
class MyClass:
    def __init__(self, value):
        self.value = value

# インスタンス化
mc = MyClass('mcです')

# 弱参照の生成
ref = weakref.WeakValueDictionary({'mc': mc})
print(ref['mc'].value)

# 参照先のオブジェクト削除
del mc

print(ref['mc'].value)

実行結果

mcです
Traceback (most recent call last):
  File "main.py", line 18, in <module>
    print(ref['mc'].value)
  File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/weakref.py", line 134, in __getitem__
    o = self.data[key]()
KeyError: 'mc'

まとめ

この記事では、Pythonで弱参照を使う方法を解説しました。

弱参照を使うことでオブジェクトを色々なところで参照しても管理は大元のみで行うことができるようになります。

それでは今回の内容はここまでです。ではまたどこかで〜( ・∀・)ノ