7
>>> from weakref import WeakValueDictionary
>>> class Foo(object):
...     pass
>>> foo = Foo()
>>> db = WeakValueDictionary()
>>> db['foo-id'] = foo
>>> del foo
>>> dict(db)
{'foo-id': <__main__.Foo object at 0x4dd946c>}

空の辞書の代わりにこれが表示されるのはなぜですか?このコードは私が期待する結果を生成することに注意してください:

>>> db2 = WeakValueDictionary()
>>> db2['disposable-id'] = Foo()
>>> dict(db2)
{}

また、(対話型インタープリターの代わりに)スクリプトを実行するときに期待どおりに動作します。

from weakref import WeakValueDictionary
class Foo(object):
    pass
foo = Foo()
db = WeakValueDictionary()
db['foo-id'] = foo
del foo
print str(dict(foo))
# prints {}
4

3 に答える 3

10

WeakValueDictionary通常の参照がない場合にエントリが削除されることを保証するものではありません。それが保証するのは、やがてガベージコレクションを妨げないということです-あなたのオブジェクトはガベージコレクション可能であり、ガベージコレクションではありません。ガベージコレクションが発生すると、エントリは表示されなくなります。

于 2012-08-19T05:47:49.200 に答える
4

インタラクティブシェルでこれを試しているだけの場合は、そのインターフェイスでのガベージコレクションの動作とグローバルスコープの操作に関係していると思います。

スクリプトからこれを試してください:

foo.py

from weakref import WeakValueDictionary

class Foo(object):
    pass

f = Foo()
d = WeakValueDictionary()
d['f'] = f 

print dict(d)
del f 
print dict(d)

その後...

$ python foo.py

{'f': <__main__.Foo object at 0x101f496d0>}
{}

次に、インタラクティブなPythonシェルからこれを試して、関数スコープの下で操作を移動します。

from weakref import WeakValueDictionary

class Foo(object):
    pass

f = Foo()
d = WeakValueDictionary()
d['f'] = f 

def main():
    global f
    print dict(d)
    del f 
    print dict(d)

main()

#{'f': <__main__.Foo object at 0x100479f10>}
#{}
于 2012-08-19T03:10:50.900 に答える
3

Python Interactive Shellでは、スコープが終了していないため、宣言する変数が自動的にガベージコレクションされ__main__ません。Pythonでのガベージコレクションは参照カウントに基づいており、明示的に行うか、現在のスコープから外れるまで、ガベージコレクションは収集されません。

同じシェルで、WeakRef関数内にロジックを実装すると、期待される結果が表示されます。これは、関数が終了すると、コントロールがスコープ外になり、オブジェクトがガベージによって収集されるためです。

そのため、@ jdi with functionの例では、必要なものが正確に表示されます。

于 2015-05-13T17:06:04.503 に答える