【问题标题】:WeakValueDictionary retaining reference to object with no more strong referencesWeakValueDictionary 保留对没有更多强引用的对象的引用
【发布时间】:2012-08-14 23:02:45
【问题描述】:
>>> 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 {}

【问题讨论】:

    标签: python mapping python-2.7 weak-references


    【解决方案1】:

    WeakValueDictionary 不保证在没有正常引用时将删除条目。它保证它不会在适当的时候阻止垃圾收集 - 您的对象是garbage collectable,而不是garbage collectable。当垃圾回收发生时,该条目将消失。

    【讨论】:

      【解决方案2】:

      如果您只是在交互式 shell 中尝试过此操作,我相信这与垃圾收集在该接口下的工作方式和全局范围操作有关。

      通过脚本试试这个:

      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 shell 中尝试这个,将操作移动到函数范围内:

      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>}
      #{}
      

      【讨论】:

      • 我还尝试在交互式解释器中导入gc 并在deling foo 之后调用gc.collect(),它消除了弱引用。显然交互式解释器不会立即收集垃圾。
      • 是的。如果没有科学的答案,我会简单地说交互式外壳不是实现行为的最佳案例。它非常适合测试,但无法被简单的可执行脚本击败。
      【解决方案3】:

      在 Python 交互式 Shell 中,无论您声明什么变量,都不会自动进行垃圾回收,因为 __main__ 中的范围还没有结束。 Python 中的垃圾收集基于引用计数,除非您明确执行此操作或脱离当前范围,否则它不会被收集。

      在同一个 shell 中,如果你在函数内部实现 WeakRef 逻辑,你会看到预期的结果,因为在完成函数后,控件超出范围并且对象被垃圾收集。

      这就是为什么@jdi with function 的示例向您展示了您想要的内容。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-07-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-05-29
        • 1970-01-01
        • 2014-07-19
        • 1970-01-01
        相关资源
        最近更新 更多