首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Python WeakValueDictionary在gc.collect()之后保留IPython中的值

Python WeakValueDictionary在gc.collect()之后保留IPython中的值
EN

Stack Overflow用户
提问于 2015-10-07 09:58:49
回答 1查看 260关注 0票数 3

我正在尝试理解Python weakref模块及其用例,因此我有以下设置:

代码语言:javascript
复制
import gc, weakref

class obj(object):
    def __init__(self, val=None):
        self._s = "Sample" if not val else " ".join(["Sample:", str(val)])
    def sample(self):
        return self._s

ol = [obj(x) for x in range(1,4)]
o1 = obj(1)
o2 = obj(2)
o3 = obj(3)

wdict1 = weakref.WeakValueDictionary({k:ol[k-1] for k in range(1,4)})

wdict2 = weakref.WeakValueDictionary()
wdict2[1] = o1
wdict2[2] = o2
wdict2[3] = o3

在运行测试之后,我可以清楚地看到,WeakValueDictionary在某种程度上保留了所有的值,尽管我已经显式地调用了gc.collect()。据我理解,并在下面的回答中解释了,调用gc.collect()应该删除所有弱引用的值。

代码语言:javascript
复制
In [2]: wdict1.items()
Out[2]: 
[(1, <__main__.obj at 0x7fea09c0be90>),
 (2, <__main__.obj at 0x7fea09c0bf10>),
 (3, <__main__.obj at 0x7fea09c0bf50>)]

In [3]: wdict2.items()
Out[3]: 
[(1, <__main__.obj at 0x7fea09c51790>),
 (2, <__main__.obj at 0x7fea09c0bed0>),
 (3, <__main__.obj at 0x7fea09c0bf90>)]

In [4]: del ol[0]

In [5]: del o1

In [6]: gc.collect()
Out[6]: 64

In [7]: wdict1.items()
Out[7]: 
[(1, <__main__.obj at 0x7fea09c0be90>),
 (2, <__main__.obj at 0x7fea09c0bf10>),
 (3, <__main__.obj at 0x7fea09c0bf50>)]

In [8]: wdict2.items()
Out[8]: 
[(1, <__main__.obj at 0x7fea09c51790>),
 (2, <__main__.obj at 0x7fea09c0bed0>),
 (3, <__main__.obj at 0x7fea09c0bf90>)]

In [9]: del ol[0]

In [10]: del o2

In [11]: gc.collect()
Out[11]: 0

In [12]: wdict1.items()
Out[12]: 
[(1, <__main__.obj at 0x7fea09c0be90>),
 (2, <__main__.obj at 0x7fea09c0bf10>),
 (3, <__main__.obj at 0x7fea09c0bf50>)]

In [13]: wdict2.items()
Out[13]: 
[(1, <__main__.obj at 0x7fea09c51790>),
 (2, <__main__.obj at 0x7fea09c0bed0>),
 (3, <__main__.obj at 0x7fea09c0bf90>)]

In [14]: weakref.getweakrefs(ol[0])
Out[14]: [<weakref at 0x7fea0ab05470; to 'obj' at 0x7fea09c0bf50>]

In [15]: weakref.getweakrefs(o3)
Out[15]: [<weakref at 0x7fea09c060b0; to 'obj' at 0x7fea09c0bf90>]

In [16]: wdict1[1].sample()
Out[16]: 'Sample: 1'

In [17]: wdict2[2].sample()
Out[17]: 'Sample: 2'

我的代码有什么问题,为什么所有弱引用的值都保持不变?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-10-07 10:38:15

问题是IPython使用以下方法保存对对象的引用-

  1. _ -上一次声明的结果。
  2. __ -第二次最后陈述的结果。
  3. ___ -第三次最后陈述的结果。
  4. In[num] -运行提示符num的语句的字符串
  5. Out[num] -提示符num语句的结果/输出。

来自文档 -

输入和输出历史记录保存在名为InOut的变量中,这些变量由提示符数字(如In[4] )键决定。输出历史中的最后三个对象也保存在变量______中。

实际上,您可以尝试运行Out[2],并看到它将是对wdict1.items()结果的引用(如果在2提示符中,您按照您在示例中所给出的方式运行了该语句)。

IPython很可能保存了大量对对象的此类引用,因此当您删除ol[0]o1之类的名称时,然后执行gc.collect。它实际上并不收集对象,因为仍然存在对对象的引用(在______Out[num]中)。

我能想到两种解决方案-

  1. 使用%xdel魔术命令删除引用,比如%xdel ol[0],而不是del ol[0]。这将导致IPython清除它保存的所有引用。基于文件-

删除一个变量,尝试从IPython的机器引用它的任何地方清除它。

  1. 您可以尝试将此测试作为脚本运行,而不是以交互方式运行,在这种情况下,这些额外的引用将不会被创建,并且您应该看到正确的行为。
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/32989283

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档