[Python-Dev] basenumber redux (original) (raw)
Alex Martelli aleaxit at gmail.com
Mon Jan 16 18:27:31 CET 2006
- Previous message: [Python-Dev] basenumber redux
- Next message: [Python-Dev] basenumber redux
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
On Jan 16, 2006, at 7:53 AM, Guido van Rossum wrote:
On 1/15/06, Alex Martelli <aleaxit at gmail.com> 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
- Previous message: [Python-Dev] basenumber redux
- Next message: [Python-Dev] basenumber redux
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]