通过删除引用

时间:2018-08-14 00:05:50

标签: python dictionary ref

我正在使用大型嵌套词典,并且正在尝试删除嵌套子词典。我想知道为什么会发生以下行为。

当我设置对字典d的引用(称为ref)时,然后更改ref并打印d,它显示d的更新版本,并添加了第三个元素。

input:
d={"a":1,"b":2}
ref=d
ref["c"]=3
print(d)

output:
{'a': 1, 'b': 2, 'c': 3}

鉴于此行为,我希望能够通过delete删除字典

input:
d={"a":1,"b":2}
ref=d
del ref
print(d)

output:
{'a': 1, 'b': 2}

我想知道在删除引用时是否有办法删除原始对象(这意味着第二个程序的输出将是错误的,因为删除了d。

2 个答案:

答案 0 :(得分:1)

del statement的行为根据所删除的内容而有所不同。稍微解释一下:

  

删除名称会从本地或全局名称空间中删除该名称的绑定

这是第二种情况。您有两个对同一个对象的引用。名称ref已被删除,但名称d仍然存在并且始终指向同一对象。

但是,属性,订阅和切片具有不同的行为:

  

对属性引用,订阅和切片的删除将传递给所涉及的主要对象

这更像第一种情况-从任一名称中删除元素都会在另一名称中反映出来

input:
d = {"a":1, "b":2}
ref = d
del ref["a"]
print(d)

output:
{'b': 2}

因此,将引用包裹在字典(或其他容器)中,将允许任何引用删除。

答案 1 :(得分:1)

del实际上并不处理任何内存分配问题,它只是unbinds a value from a name,然后将该对象的引用计数减一。在给定单个引用的情况下,无法系统地解除绑定对象的所有名称。

直到引用计数降至0之后的某个点才对对象进行垃圾回收。您可以使用sys.getrefcount方法(由于临时原因,通常比实际值高一个)来查看对象的引用计数方法本身内的引用)。

我们可以在实践中使用此方法和__del__方法(仅当对象的引用计数减为0时调用)来演示del

>>> # print something when refcount == 0 and object is about to be collected
>>> class Deleted:
...     def __del__(self):
...         print("actually deleted")
...
>>> a = Deleted()
>>> # just a
>>> sys.getrefcount(a) - 1
1
>>> b = a
>>> # a and b
>>> sys.getrefcount(a) - 1
2
>>> del a
>>> # now it's just b
>>> sys.getrefcount(b) - 1
1
>>> del b
actually deleted

如果您想了解更多有关内部工作原理的信息,请查看内部调用中的C API文档以进行引用计数,并查看gc module,这是最高的自检垃圾收集子系统的高级python接口。

鉴于您的特定问题,由于您正在使用可变类型的字典,因此您可以clear字典:

>>> a = {"a": 1}
>>> b = a
>>> # will clear the dict that both a and b are referencing
>>> b.clear()
>>> a
{}

或者,您可以使用等效的range语法清除字典del a[:]