我正在使用大型嵌套词典,并且正在尝试删除嵌套子词典。我想知道为什么会发生以下行为。
当我设置对字典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。
答案 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[:]
。