「ゼロから作るディープラーニング 3 」の 「ステップ17 メモリ管理と循環参照」において、 weakrefによる弱参照化が紹介されていましたので、メモ
weakref.ref() を使用する場合
参考url https://yumarublog.com/python/weakref/
import sys import weakref def main(): mem_leak_proc() no_mem_leak_proc() def mem_leak_proc(): member1 = Member(1, "tim") ref1 = member1 # 強参照 作成 del member1 # 参照元 object削除 # 強参照の為、上記でdelしているが、参照先では残ります print(sys._getframe().f_code.co_name, ref1.name) def no_mem_leak_proc(): member1 = Member(1, "tim") # 弱参照 生成 ref1 = weakref.ref( member1 ) print(sys._getframe().f_code.co_name, ref1().name) # 参照元 object削除 del member1 if ref1() == None: print(sys._getframe().f_code.co_name, "ref1 not exist") else: print(sys._getframe().f_code.co_name, "ref1 exists") class Member: def __init__(self, id, name): self.id = id self.name = name if __name__ == '__main__': main()
↑こう書くと↓こう表示されます
> python foo_2.py mem_leak_proc tim no_mem_leak_proc tim None no_mem_leak_proc ref1 not exist
weakref.WeakValueDictionary() を使用する場合
参考url https://qiita.com/pashango2/items/fb1e5e79589279c5a861
import sys import weakref def main(): mem_leak_proc() no_mem_leak_proc() def mem_leak_proc(): # idをkeyにした辞書 members_dict = { x.id : x for x in [ Member(1, "tim"), Member(2, "matthew"), Member(3, "Jack") ] } # 上記を元にnameをkeyにした辞書.(循環参照) names_dict = {x.name: x for x in members_dict.values()} del members_dict[1] # 上記でdelしているが、循環参照により、以下は値が残り、 # このメモリリーク?を改善するには、del names_dict['tim'] も必要 name_key = "tim" if name_key in names_dict: print(sys._getframe().f_code.co_name, name_key,"exists.") else: print(sys._getframe().f_code.co_name, name_key,"don't exist.") def no_mem_leak_proc(): # idをkeyにした辞書 members_dict = { x.id : x for x in [ Member(1, "tim"), Member(2, "matthew"), Member(3, "Jack") ] } names_dict = weakref.WeakValueDictionary( {x.name: x for x in members_dict.values()} ) del members_dict[1] name_key = "tim" if name_key in names_dict: print(sys._getframe().f_code.co_name, name_key,"exists.") else: print(sys._getframe().f_code.co_name, name_key,"don't exist.") class Member: def __init__(self, id, name): self.id = id self.name = name if __name__ == '__main__': main()
↑こう書くと↓こう表示されます
>python foo.py mem_leak_proc tim exists. no_mem_leak_proc tim don't exist.