weakref

知識としては知っていたが始めてweakrefが必要だと感じるシチュエーションにぶつかった。まずは短いコードで挙動を確認してみる。

from weakref import WeakValueDictionary

class Foo(list):
    pass

def make():
    x = Foo([0])
    y = Foo([1, x])
    z = Foo([2, y])
    return WeakValueDictionary(x=x, y=y, z=z), z

d, cur = make()
print cur
print d.items()
cur = cur[1]
print cur
print d.items()

出力は下記

[2, [1, [0]]]
[('y', [1, [0]]), ('x', [0]), ('z', [2, [1, [0]]])]
[1, [0]]
[('y', [1, [0]]), ('x', [0])]

zへの参照がなくなるとdの中身からも消えている。

ちなみにlistやintを直接いれようとすると「TypeError: cannot create weak reference to 'list' object」というエラーが出る。あと対話的インタプリタで試していて消えると思ったタイミングで消えなくて戸惑った。暗黙の「_」があるので、例えば代入は式ではないので更新されなくて_が掴んだままになるし、d.items()するとそれが_に入るのでそこからの参照が残る、という罠。「消えないなおかしいなー」と思ってglobals()してみて、もう一度確認すると今度は消えているw