【问题标题】:I deleted my dict, but my dict_keys don't mind, why is that?我删除了我的 dict,但我的 dict_keys 不介意,这是为什么呢?
【发布时间】:2017-02-10 14:19:49
【问题描述】:

由于dict.keys(和dict.itemsdict.values类似)返回字典对象的视图,我假设删除它们产生的字典实际上对dict_keys产生影响,我们得到了它们从。

用一个简单的字典和它的键:

d = {i:i for i in range(20)}
k = d.keys()  # similarly with d.values and d.items

显然,情况并非如此:

del d
i = iter(k)
list(i) # works fine and prints the keys

有人知道为什么会这样吗?

【问题讨论】:

    标签: python python-3.x dictionary


    【解决方案1】:

    del d 删除了变量 d,但它所引用的对象 如果有其他引用,则将继续存在。你不需要字典视图来观察这个:

    >>> d = {i:i for i in range(5)}
    >>> dd = d
    >>> d['x'] = 'x'
    >>> del d
    >>> d
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    NameError: name 'd' is not defined
    >>> dd
    {0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 'x': 'x'}
    

    d['x']='x' 行表明dd=d 确实复制字典本身,它只是做一个额外的引用。)

    还对比clear的行为,它修改了实际的对象:

    >>> d = {i:i for i in range(5)}
    >>> k = d.keys()
    >>> del d
    >>> list(k)
    [0, 1, 2, 3, 4]
    
    >>> d = {i:i for i in range(5)}
    >>> k = d.keys()
    >>> d.clear()
    >>> list(k)
    []
    

    【讨论】:

      【解决方案2】:

      在对象上调用d.keys() 只会增加字典对象的引用计数; del d 不会为名称为 d 的对象触发垃圾收集器,因为引用将始终大于零。

      当使用sys.getrefcount 调用d.keys() 时,您可以看到字典对象的引用计数增加:

      from sys import getrefcount
      d = {i:i for i in range(20)}
      getrefcount(d) # 2
      k = d.keys() 
      getrefcount(d) # 3 (+1 due to d.keys())
      

      在构造字典的调用中查看这个reference increment can be seen

      Py_INCREF(dict);
      dv->dv_dict = (PyDictObject *)dict;
      

      在对象存储到视图对象结构的相应条目之前完成。

      由于视图实际上只是一个具有对底层 dict 引用的可迭代对象,因此您还可以更深入一步,在获取其迭代器后删除键对象,并且仍然能够获取值:

      i = iter(k) # +1 reference
      del k, d
      next(i)     # 0
      

      iter(k) increases the reference count 将原始字典再次,使对象远离集合。

      【讨论】:

      • 是的@AlexFung,当你能够正确地做到这一点时,这是允许的(我尽力做到这一点)。见这里Can I answer my own question?
      • @JimFasarakis-Hilliard 很酷。我不知道鼓励立即自我回答
      猜你喜欢
      • 2022-11-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多