我希望能够获取对类的任何现有对象实例的引用元组。我想到的是:
import gc def instances(theClass): instances = [] gc.collect() for i in gc.get_referrers(theClass): if isinstance(i, theClass): instances.append(i) return tuple(instances)
如果在 Python 解释器提示符下输入上述代码,那么您可以执行以下操作:
>>> class MyClass(object): >>> pass >>> c = MyClass() >>> instances(MyClass) (<__main__.MyClass object at 0x100c616d0>,)
太棒了。但是看起来gc.collect()函数内部实际上什么都没做:
gc.collect()
>>> del c >>> instances(MyClass) (<__main__.MyClass object at 0x100c616d0>,)
但gc.collect()在函数之外有效:
>>> del c >>> gc.collect() >>> instances(MyClass) ()
因此,我的问题是:如何gc.collect()在函数内部实际执行完整的收集(以及为什么它不能按原样工作)? 附带的问题是:有没有更好的方法来实现相同的目标,即返回包含对特定类的对象实例的引用的元组?
注意:所有这些都是在 Python 2.7.3 中尝试的。我还没有在 Python 3 中尝试过,但我的目标是拥有一个可以在其中运行的函数(或者至少可以使用 2to3 进行转换)。
经过编辑(根据下面的答案)以澄清该问题实际上与交互模式有关,而不是与gc.collect()功能本身有关。
当你在交互模式下工作时,有一个神奇的内置变量_保存着你运行的最后一个表达式语句的结果:
_
>>> 3 + 4 7 >>> _ 7
当删除c变量时,del c它不再是一个表达式,因此_保持不变:
c
del c
>>> c = MyClass() >>> instances(MyClass) (<__main__.MyClass object at 0x00000000022E1748>,) >>> del c >>> _ (<__main__.MyClass object at 0x00000000022E1748>,)
_保留对MyClass实例的引用。当您调用时gc.collect(),这是一个表达式,因此的返回值gc.collect()将替换的旧值_,并c最终被收集。它与垃圾收集器没有任何关系;任何表达式都可以:
MyClass
>>> 4 4 >>> instances(MyClass) ()
你的理解是正确的!在 Python 的交互模式下,内置变量 _ 总是保存上一个表达式的结果。因此,当执行 del c 时,因为 del 语句本身不返回任何值,它不会更新 _。在这个情况下, _ 仍然指向之前的 instances(MyClass) 调用的结果,这就是为什么 MyClass 实例仍然存在的原因。
del
instances(MyClass)
当你执行一个表达式(比如调用 gc.collect() 或输入一个数值),返回值会更新 _,从而释放对之前对象的引用。如果 c 是唯一对 MyClass 实例的引用,这样做会允许垃圾回收器在下次运行时回收该实例。
简单来说,_ 仅仅是一个持有上一个表达式结果的变量,并不与垃圾回收直接相关,但由于 _ 持有的对象也算作引用,它可能会暂时延长对象的生命周期直到下一个表达式更新它。