我注意到有关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
:
>>> 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解释器施加任何特殊限制这......我只是想知道发生了什么事情让它忽略了这样的匿名对象。)
答案 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,它将最后的结果存储在_
中。所以它毕竟不是真的匿名。