[Python-Dev] 2.6 object.__init__ & deling __new__

Nick Coghlan ncoghlan at gmail.com
Wed Jul 15 15:41:40 CEST 2009


Dino Viehland wrote:
> Based upon the behavior I'm seeing it seems to me that the
> presence of __new__ / __init__ must be getting cached somewhere
> and the deletion isn't updating the cache and that's specifically
> what struck me as odd here.

Digging through typeobject.c, it isn't clear to me why this wouldn't be
getting picked up.

If all is working correctly:

1. When the class is created, tp_new and tp_init are copied from the
base class (see inherit_special and inherit_slots)

2. When object_new and object_init are called they compare the values
stored in the tp_new and tp_init slots with their own function addresses
to decide whether or not to raise the warning

3. When either of those is deleted, the update_slots call in
type_setattro should fix up the slot inheritance, and hence affect
future calls to __new__ and __init__

That said, the following comments in update_one_slot() are leading me to
wonder if Guido might owe Dino a beer:

{
        /* The __new__ wrapper is not a wrapper descriptor,
            so must be special-cased differently.
            If we don't do this, creating an instance will
            always use slot_tp_new which will look up
            __new__ in the MRO which will call tp_new_wrapper
            which will look through the base classes looking
            for a static base and call its tp_new (usually
            PyType_GenericNew), after performing various
            sanity checks and constructing a new argument
            list.  Cut all that nonsense short -- this speeds
            up instance creation tremendously. */
        specific = (void *)type->tp_new;
        /* XXX I'm not 100% sure that there isn't a hole
            in this reasoning that requires additional
            sanity checks.  I'll buy the first person to
            point out a bug in this reasoning a beer. */
}

I *think* this logic may be getting confused when update_one_slot() is
called immediately after the "del x.__new__" call has stuffed a NULL
into the tp_new slot. In the normal class creation case the tp_new
method will have been copied down from the parent class so the
conditions when update_one_slot() gets called are different (ditto for
when you actually *set* x.__new__ rather than delete it).

If nobody else gets anywhere with this I should have a chance to
actually play with it (rather than just reading code) tomorrow evening.

Cheers,
Nick.

-- 
Nick Coghlan   |   ncoghlan at gmail.com   |   Brisbane, Australia
---------------------------------------------------------------


More information about the Python-Dev mailing list