小能豆

Python:在交互模式下使用 gc 模块的不同行为

py

我希望能够获取对类的任何现有对象实例的引用元组。我想到的是:

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()函数内部实际上什么都没做:

>>> 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()功能本身有关。


阅读 6

收藏
2024-11-04

共2个答案

小能豆

当你在交互模式下工作时,有一个神奇的内置变量_保存着你运行的最后一个表达式语句的结果:

>>> 3 + 4
7
>>> _
7

当删除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最终被收集。它与垃圾收集器没有任何关系;任何表达式都可以:

>>> 4
4
>>> instances(MyClass)
()
2024-11-04
小能豆

你的理解是正确的!在 Python 的交互模式下,内置变量 _ 总是保存上一个表达式的结果。因此,当执行 del c 时,因为 del 语句本身不返回任何值,它不会更新 _。在这个情况下, _ 仍然指向之前的 instances(MyClass) 调用的结果,这就是为什么 MyClass 实例仍然存在的原因。

当你执行一个表达式(比如调用 gc.collect() 或输入一个数值),返回值会更新 _,从而释放对之前对象的引用。如果 c 是唯一对 MyClass 实例的引用,这样做会允许垃圾回收器在下次运行时回收该实例。

简单来说,_ 仅仅是一个持有上一个表达式结果的变量,并不与垃圾回收直接相关,但由于 _ 持有的对象也算作引用,它可能会暂时延长对象的生命周期直到下一个表达式更新它。

2024-11-04