On Jan 16, 2006, at 7:53 AM, Guido van Rossum wrote: > On 1/15/06, Alex Martelli <[EMAIL PROTECTED]> wrote: >> Now, today, I have _again_ been bit by the lack of basenumber (by a >> bug of mine, fixed by adding decimal.Decimal to a long tuple of >> classes to be passed to an isinstance call -- I hadn't run that >> particular numeric code of mine since the time of Python 2.3, >> apparently), so I'm back to pining for it. > > As you already suspected, I think a PEP is needed. The intent of
I'll be happy to write it, if it stands any chance. > basestring was to *only* be used as the base class for *built-in* > string types. Clearly what you're proposing is different (Decimal is > not built-in -- not yet anyway). I can't find a PEP describing this restriction of basestring, and I don't see why a coder who needs to implement another kind of character string shouldn't subclass basestring, so that those instances pass an isinstance test on basestring which is quite likely to be found e.g. in the standard library. Implementing different kinds of numbers is more likely than implementing different kinds of strings, of course. > Like other posters, I suspect that the best way of detecting numbers > might be some other kind of test, not necessarily a call to > isinstance(). I've tended to use a try/except around x+0 to detect if "x is a number". But that's NOT how the standard library does it -- rather, it has isinstance tests (often forgetting long in the tuple of types), as I pointed out in my mails on the subject back in 2003 (google for [basenumber site:python.org], there aren't many). I will reproduce those in the PEP, of course, if I do write one. The x+0 test has been criticized in the past because x COULD be an instance of a type which defines an __add__ which has side effects, or a very inclusive __add__ which happens to accept an int argument even though the type is NOT meant to be a number. These could be seen as design defects of x's type, of course. A second argument against the x+0 test is performance. A third argument against it is asymmetry: why should I use completely different approaches to check if x is "some kind of string", vs checking if x is "some kind of number"? Once upon a time I used x +'' (with try/except around it) to check for stringness, but the introduction of basestring strongly signaled that this was not the "one obvious way" any more. > > It would also help to explain the user case more. ("I've been bitten" > doesn't convey a lot of information. :-) isinstance with a tuple of number types, where the tuple did not include Decimal (because when I developed and tested that module, Decimal wasn't around yet). That's the problem of using isinstance without a "flag class" like basestring: one is hardwiring a specific tuple of types as being "singled out" for different treatment. If a new type comes up (be it for the standard library or some extension) there's no way to respect the "open-closed principle", leaving the affected module "closed to changes" yet "open for extension". In this way, using isinstance with a "hardwired" tuple of types is open to the same objections as "type-switching": it produces code that is not extensible to new types beyond those specific ones it had considered at coding time. I have the same issue in the C-coded extension gmpy: I want (e.g.) a gmpy.mpq to be able to be constructed by passing any number as the argument, but I have no good way to say "what's a number", so I use rather dirty tricks -- in particular, I've had to tweak things in a weird direction in the latest gmpy to accomodate Python 2.4 (specifically Decimal). Since "being a number" is a protocol (albeit, like "being a string", a rather peculiar one -- "the verb TO BE" is always fraught;-), other traditional possibilities for supporting it are introducing a special method or flag attribute such as "__isanumber__" (either callable, or flagging numberhood just by its presence). But introducing flag- abstract-class basenumber is more consistent with what was done for strings and affords a simpler test via isinstance. Of course _if_ PEP 246 was accepted, anybody could add more types to the set of those which "can be adapted to being numbers", but an object to denote that protocol should still be there (since the standard library does need to test for numberhood in a few places). If I do write the PEP, should it be just about basenumber, or should it include baseinteger as well? The case for the latter is IMHO still good but a bit weaker; it would be nice to be able to code 'xy' * Z without having str.__rmul__ perform a hardcoded test on Z being specifically an int or a long, making "other kinds of integers" (e.g. gmpy.mpz instances) smoothly substitutable for ints everywhere (similarly for somelist[Z], of course). Right now I have to pepper my code with int(Z) casts when Z is a gmpy.mpz and I need to use it to index or multiply a sequence, which isn't nice for either readability or performance, but (in my experience so far, at least) these aren't _frequent_ needs, just occasional ones. Thanks, Alex _______________________________________________ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com