【问题标题】:Deleting an object used as key in dict does not remove the correspondent key in the dict删除字典中用作键的对象不会删除字典中的对应键
【发布时间】:2016-12-20 21:31:53
【问题描述】:

我有一个以对象实例为键的字典:

outputs = {instance1:instance1.id, instance2:instance2.id}

当我从字典外删除对象时,对应的键没有从字典中删除,这不是我所期望的。

我想要实现的是,当从字典外部删除对象时,键也从字典中消失。

【问题讨论】:

  • 删除对象是什么意思?向我们展示不起作用的代码。
  • 那是因为 instance1 或 instance2 没有在字典中引用,而是计算并存储了它们的哈希值以供查找。
  • 这些对象的引用计数不能降为零,因为您在字典中有对它们的引用。如果您需要不同的行为,请将密钥设为 weak reference
  • 为什么需要map来查找实例的id?你不能只访问 instance.id 吗?
  • 也许你想要WeakKeyDictionary?您还没有定义“从字典外部删除对象”的含义。

标签: python dictionary instance


【解决方案1】:

实际上你存储在变量中的对象和字典中用作键的对象并不完全相同。它们是对内存中同一个对象的两个不同引用。

我们来看下面的例子:

class Foo(object):

    def __init__(self, _repr):
        self._repr = _repr

    def __repr__(self):
        return '{}-{}'.format(self._repr, id(self))

 a = Foo('f1')
 # The count returned by getrefcount() is generally one higher than you might expect, because it includes the (temporary) reference as an argument to getrefcount()
 print(sys.getrefcount(a) - 1) # Out: 1
 d = {a: 'value'} # Out {f1-139822435732560: 'value'}
 print(sys.getrefcount(a) - 1) # Out: 2
 a._repr = 'f2'
 print(d) # Out {f2-139822435732560: 'value'}

这证明了 dict 创建了对主对象的新引用。并且因为 Python 的主要内存管理方法使用了引用计数:

Python 记录所有对 该对象,当没有剩余时,该对象被删除。

因此,如果您删除存储在变量 del a 中的引用,则存储在 dict 中的引用将保留。

del a
print(sys.getrefcount(d.keys()[0]) - 1) # Out: 1

这会使您的 dict 变得不稳定,因为您可以更多地访问您的数据,我建议使用变量引用从 dict 中删除数据而不是删除对象。

del d[a]
print(sys.getrefcount(a) - 1) # Out: 1
del a

【讨论】:

    【解决方案2】:

    在删除对象之前,您必须从字典中删除键。

    del outputs[instance1]
    

    这是因为字典没有将对象存储为键,而是从它生成的哈希。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-09-02
      • 2021-04-28
      • 2019-05-04
      • 2022-01-10
      • 2022-01-14
      相关资源
      最近更新 更多