删除在dict中用作键的对象不会删除dict中的对应键

时间:2016-12-20 12:49:28

标签: python dictionary instance

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

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

当我从dict外部删除对象时,对应的密钥不会从字典中删除,这不是我所期望的。

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

2 个答案:

答案 0 :(得分:2)

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

我们来看下面的例子:

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为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

答案 1 :(得分:1)

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

del outputs[instance1]
发生这种情况是因为dict不会将对象存储为键,而是从其生成的哈希值。