Python

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

この記事では、Pythonで弱参照を使う方法を解説します。弱参照とは、ガベージコレクタから参照していると思われない参照で、オブジェクトの参照が弱参照のみになった場合、そのオブジェクトは削除してもよいオブジェクトとして認識されます。

弱参照の使い方

弱参照は、weakrefモジュールを使うことで簡単に扱うことができます。

import weakref
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で弱参照を使う方法を解説しました。

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

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

最短3か月でエンジニア転職『DMM WEBCAMP COMMIT』