Why aren't anonymous (C)Python objects deallocated immediately?
Question: I noticed something about CPython's object deallocation which piqued my
curiosity. Let's say I define a type that prints a message from its
`tp_dealloc` function:

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

I've also done the right thing with the allocator:

    
    
    PyMODINIT_FUNC initpyfoo(void) 
    {
        PyObject* m;
    
        pyfoo_BarType.tp_new = PyType_GenericNew;
        /* ... */
    }
    

I compile it and run a Python 2.6 interpreter in the directory with
`pyfoo.so`:

    
    
    >>> import pyfoo
    >>> a = pyfoo.Bar()
    >>> a = None
    Bar freed
    >>> quit()
    

This is what I'd expect... the reference count drops to zero and the `Bar`
object is collected. But now if I do:

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

... the `Bar` object is not collected until the interpreter exits. But surely
the reference count on the `Bar` object created anonymously is zero, just like
the one explicitly assigned. So why is it not deallocated immediately after
creation?

(I'm doing this on Debian Squeeze with Python 2.6.6 compiled with GCC 4.4.5. I
know it's not a "bug", I know Python-the-language doesn't place any particular
constraints on Python interpreters this... I just want to know what is going
on under the hood that makes it ignore anonymous objects like this.)


Answer: Because after you called `pyfoo.Bar()` the object is still accessible using
the special object `_`

This works with pure Python, by the way:

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

And later:

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

Notice how reassigning `_` implicitly deleted the `X` object?

