[Python-Dev] PEP 253: Subtyping Built-in Types
Guido van Rossum
Sun, 22 Jul 2001 12:42:49 -0400
> Hmm, I don't like these class methods, but it would probably
> help with the problem...
> from mx.DateTime import DateTime
> dt1 = DateTime(2001,1,16)
> dt2 = DateTime.From("16. Januar 2001")
> Still looks silly to me... (I don't like these class methods).
Maybe it's time you started to like them. :-)
> > I've been thinking about this. I don't think that's quite the right
> > protocol; I don't want to complicate the DECREF macro any more. I
> > think that tp_dealloc must call tp_del and then decide whether to
> > proceed depending on the refcount.
> Have you tried to move the decref action into a separate function
> (which is only called in case the refcount reaches 0) ? I think
> that this could in fact enhance the overall performance since
> the compiler can then decide whether or not to inline the relevant
> I wonder what the impact would be...
My gut tells me that the compiler will usually *not* inline it, and
then it will slow deallocation down by one extra function call. And
if the compiler *does* inline it, it's code bloat. So either way you
lose, my gut tells me. (The dealloc functions for most common types
are very fast and I would hate to see them slow down.)
> Good, so overriding the tp_alloc/free slots is generally not
> a wise thing to do, I guess.
If the base type has a custom free list (like the int type does), you
*have* to override it if the instances of the subtype are larger than
the base type. Currently int doesn't allow subtyping yet because I
haven't refactored its code in this area yet.
> > > - Could the generic APIs perhaps fall back to tp_getattr to make
> > > the transition from classic types to base types a little easier ?
> > I'd rather not: that would prevent discovery of attributes supported
> > by the classic tp_getattr. The beauty of the new scheme is that *all*
> > attributes (methods and data) are listed in the type's __dict__.
> Uhm, I think you misunderstood me: tp_getattr is not used anymore
> once the Python interpreter finds a tp_getattro slot
> implementation, so there's nothing to prevent ;-):
> PyObject_GetAttr() does not use tp_getattr if tp_getattro is
> defined, while PyObject_GetAttrString() prefers tp_getattr over
> tp_getattro -- something is not symmertic here !
> As a result, dir() finds the __members__ attribute which lists
> the attributes (it uses PyObject_GetAttrString(), but
> instance.attribute does not work because it uses PyObject_GetAttr().
The simplified rule is that a type should only provide *either*
tp_getattr *or* tp_getattro, and likewise for set. The complete rule
is that if you insist on having both tp_getattr and tp_getattro, they
should implement the same semantics -- tp_getattr should be faster
when PyObject_GetAttrString() is called, and tp_getattro should be
faster when PyObject_GetAttr() is called.
Apparently you left your tp_getattr implementation in place but added
PyObject_GenericGetAttr to the tp_getattro slot -- this simply doesn't
follow the rules.
--Guido van Rossum (home page: http://www.python.org/~guido/)