[Python-Dev] reflections on basestring -- and other abstract basetypes

Alex Martelli aleaxit at yahoo.com
Sun Nov 2 17:19:42 EST 2003

1. Shouldn't class UserString.UserString inherit from basestring?  After all,
    basestring exists specifically in order to encourage typetests of the form
    isinstance(x, basestring) -- wouldn't it be better if such tests could
    also catch "user-tweaked strings" derived from UserString ... ?

2. If we do want to encourage such typetest idioms, it might be a good idea
   to provide some other such abstract basetypes for the purpose.

   For example, I see quite a few cases of isinstance(x, (int,long,gmpy.mpz))
   in my code -- and that, despite the fact that I'm not enamoured of
   typetesting as a general idea and that I'm quite aware that this kind of
   check could miss some other kind of user-coded "integeroid number".

   If there was an abstract basetype, say "baseinteger", from which int and
   long derived, I'd be happy to tweak gmpy to make mpz subclass it (in 2.4
   and later versions of Python only, of course) and allow such typetests to
   happen more smoothly, faster and with more generality too.

3. And perhaps baseinteger (and float and complex) should all subclass yet
    another basetype, say "basenumber"?  Why not?  I admit that right now
    I have no use cases where I _do_ want to accept complex numbers as
    well as int, long, float, and gmpy thingies (so, maybe there should be a
    more specific "basereal" keeping complex out...?), but apart from this
    detail such an abstract basetype would be similarly useful (in practice
    I would use it since I do not expect complex in my apps anyway).

4. Furthermore, providing "basenumber" would let user-coded classes "flag"
    in a simple and direct way "I'm emulating numbers".  This might well be
    useful _to Python itself_...
    Right now, I'm stuck for an answer to the bug that a user-coded class
    which exposes __mul__ but not __rmul__ happens to support its instances
    being multiplied by an integer on the right -- quite surprising to users!
    The problem is that this behavior is apparently expected, though not
    documented, when the user-coded class is trying to simulate a _sequence_
    rather than a number.  So, I can't just take the peculiar "accidental
    commutativity with integers only" away.
    IF a user class could flag itself as "numeroid" by inheriting basenumber,
    THEN the "accidental commutativity" COULD be easily removed at least
    for such classes.

5. in fact, now that we fill in type descriptor slots bases on user-coded
    classes' special methods, I suspect this isn't the only such issue.  While
    "flagging" (inheriting one of the abstract basetypes) would be entirely
    optional for user-coded classes, it would at least provide a way to
    _explicitly disambiguate_ what it is that the user-coded class IS trying
    to emulate, if the user wants to.

6. of course, for that to be any use, the various basetypes should not be
    "ambiguously" multiply inheritable from.  Right now, is isnt so...:

>>> class x(basestring, int): pass
>>> isinstance(x(), int)
>>> isinstance(x(), basestring)

...does anybody see any problem if, in 2.4, we take away the ability to
multiply inherit from basestring AND also from another builtin type which 
does not in turn inherit from basestring...?  I have the impression that
right now this is working "sort of accidentally", rather than by design.

7. one might of course think of other perhaps-useful abstract basetypes,
    such as e.g. basesequence or basemapping -- right now the new
    forthcoming built-in 'reverse' is trying to avoid "accidentally working"
    on mappings by featuretesting for (e.g.) has_key, but if the user
    could optionally subclass either of these abstract basetypes (but not
    both at once, see [6]:-), that might ease reverse's task in some cases.

    Why, such abstract basetypes might even make operator.isMappingType
    useful again -- right now, of course:
>>> operator.isMappingType([])
    and therefore there isn't much point in that function:-).

    But I think that points 1-6 may be enough to discuss for the moment
    (and I brace myself for the flames of the antitypetesters -- why, if I
    hadn't matured this idea myself I might well be one of the flamers:-)
    so I have no concrete proposals sub [7] -- yet.

<donning suit="asbestos">
   ...just a sec...

Ok, ready -- fire away!


More information about the Python-Dev mailing list