删除用作字典中键的对象不会删除字典中对应的键

Deleting an object used as key in dict does not remove the correspondent key in the dict

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

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

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

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

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

del outputs[instance1]

发生这种情况是因为 dict 没有将对象存储为键,而是从中生成的散列。

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

举个例子:

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'}

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

Python keeps a count of all the references to the object, and when there are none left, the object is deleted.

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

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

这会使你的字典变得不稳定,因为你对你的数据有更多的访问权限,我建议使用变量引用从字典中删除数据,而不是删除对象。

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