为什么不立即取消分配匿名(C)Python对象?

时间:2010-11-09 02:23:12

标签: python garbage-collection

我注意到有关CPython的对象释放的一些事情引起了我的好奇心。假设我定义了一个从tp_dealloc函数打印消息的类型:

static void pyfoo_Bar_dealloc(pyfoo_Bar* self)
{    
    PySys_WriteStdout("Bar freed\n");   
    self->ob_type->tp_free((PyObject*)self);
}

我也使用分配器做了正确的事情:

PyMODINIT_FUNC initpyfoo(void) 
{
    PyObject* m;

    pyfoo_BarType.tp_new = PyType_GenericNew;
    /* ... */
}

我编译它并在pyfoo.so

目录中运行Python 2.6解释器
>>> import pyfoo
>>> a = pyfoo.Bar()
>>> a = None
Bar freed
>>> quit()

这是我所期望的......引用计数降为零,并收集Bar对象。但现在如果我这样做:

>>> import pyfoo
>>> pyfoo.Bar()
<pyfoo.Bar object at 0x7f7c6d8f2080>
>>> quit()
Bar freed

...在解释器退出之前,不会收集Bar对象。但肯定匿名创建的Bar对象的引用计数为零,就像显式分配的那个一样。那么为什么创建后不立即解除分配?

(我在Debian Squeeze上用Python 2.6.6编译了GCC 4.4.5。我知道这不是一个“bug”,我知道Python-the-language没有对Python解释器施加任何特殊限制这......我只是想知道发生了什么事情让它忽略了这样的匿名对象。)

2 个答案:

答案 0 :(得分:8)

因为在您致电pyfoo.Bar()后,仍可使用特殊对象_

访问该对象

顺便说一下,这适用于纯Python:

class X:
    def __del__(self):
        print 'deleted'

后来:

 >>>a = X()
 >>>a = None
 deleted
 >>>X()
 <__main__.X instance at 0x7f391bb066c8> 
 >>> _
 <__main__.X instance at 0x7f391bb066c8>
 >>> 3 # causes _ to be reassigned
 deleted
 3

请注意重新分配_如何隐式删除X对象?

答案 1 :(得分:3)

因为您正在使用REPL,它将最后的结果存储在_中。所以它毕竟不是真的匿名。