如何在Python中删除对象的所有引用?

20

假设你有如下内容:

x = "something"
b = x
l = [b]

如何删除只有一个引用(比如x)的对象?

del x不能完成任务;例如,对象仍然可以从b中访问到。


3
你所谈论的这个 a 在哪里? - John La Rooy
3
为什么你想要这样做? - SilentGhost
在字符串被删除后,你建议b和l指向什么?或者你真的想要删除x、b和l吗? - phkahler
我想指向类似于“已删除”的东西,例如。 - Juanjo Conti
@JuanjoConti 删除的对象会在GC算法决定时回收。删除后,您没有理由引用已删除的对象,那么您为什么要在意它们呢?您试图解决什么具体的编程问题?您只是试图使它们在调试器视图中看起来已被删除或者其他什么(在这种情况下,您可以将它们的__del__方法覆盖为零,或者使用0xdeadbeef)吗?还是您正在调试实际的竞争条件,在这种情况下,它们在被删除但尚未被GC回收之前实际上以某种方式被引用了(可能是线程问题)?或者其他原因? - smci
1
“这个对象只有一个引用,比如说x?”“从b仍然可以访问到这个对象”这是矛盾的。 x不是“这个对象”,x该对象的名称(在您的术语中,是对它的引用)。 b也是如此。因此,它有两个名称,而对其中一个名称使用del仍然会使其保留一个名称。 - Karl Knechtel
3个回答

21

不行。Python有一个垃圾回收器,它具有非常强的领土问题 - 它不会干扰您创建对象,您不能干扰它删除对象。

简单来说,这是不可能做到的,而且有很好的理由。

例如,如果您的需求来自于缓存算法等保留引用但不应阻止数据在无人使用时被垃圾回收的情况,您可以查看 weakref


1
目的是确保该对象不会再次被使用。 - Juanjo Conti
1
@Juanjo,然后以适当的编程方式执行此操作。您的对象应允许您“关闭”主题或任何您想要执行的操作。这并没有什么神奇的。就像文件必须被关闭一样,无论有多少函数已经读取/写入它。 - abyx
1
@Juanjo:删除一个元素并不能确保它不会再次被使用。事实上,如果它再次被使用,你的程序将会崩溃。明智地编写你的代码,不要使用你不想使用的对象。 - Xavier Ho
1
是的,放松点,如果你删除了一个引用,也不会有孩子死亡。 - Omar Gonzalez

12

我目前唯一看到的解决方案是,你应该确保持有对x的唯一引用,其他任何人都不能获取x本身,而只能获取指向x的弱引用。弱引用在weakref模块中实现,你可以这样使用:

>>> import weakref
>>> class TestClass(object):
...     def bark(self):
...         print "woof!"
...     def __del__(self):
...         print "destructor called"
...
>>> x = TestClass()
>>> b = weakref.proxy(x)
>>> b
<weakproxy at 0x7fa44dbddd08; to TestClass at 0x7fa44f9093d0>
>>> b.bark()
woof!
>>> del x
destructor called
>>> b.bark()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ReferenceError: weakly-referenced object no longer exists

请注意,不是所有类都可以被弱引用。特别地,大多数内置类型不能被弱引用。一些内置类型可以在子类化它们时进行弱引用(例如 dict),但其他类型不行(例如 int)。


1
str不能被弱引用,即使您子类化它也不行。弱引用字符串会打开巨大的问题;例如,Python解释器可能选择“内部化”字符串对象并将其保留在内存中,即使没有对它的引用,希望它以后可能有用。通常解释器会这样做来处理小字符串和整数,但是您也可以选择使用 intern内置函数来内部化一个字符串(至少在 Python 2.x 中)。 - Tamás

4
你不需要这样做,这正是重点所在。想象一下,如果 l 在你无法控制的库中,它有权利期望集合元素不会消失。

此外,想象一下如果情况相反,你会在 SO 上看到这样的问题:“如何防止其他人删除我的对象?” 作为语言设计者,你无法同时满足这两个需求。


我不会删除整个列表,只会删除一个元素。 - Juanjo Conti
该库保存了对对象的引用;根据Python语言规则,它可以依赖于该引用来保持对象的存活。 - MSalters

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接