# How can I tell when a string is in fact a number?

Alex Martelli aleaxit at yahoo.com
Wed Nov 8 09:55:27 CET 2000

```"Thomas Gagne" <tgagne at ix.netcom.com> wrote in message
news:3A08D246.7FF1D355 at ix.netcom.com...
> OK.  You have a point.  Ignore what it returns for now, but I think having
a
> method #isNumber would be useful, and very self-documenting.

You mean, a method '#isNumber' of string objects as opposed to the
existing method 'isdigit' of the same objects (which we had all

Well, maybe, but it's a tricky question to determine what strings should
meet the 'is a number' condition!  To wit, consider such strings as...:
1234
1234123412341234
1234123412341234L
7,234,918
7,234,918.00
+77
-41
3.1415926
23j
23e2
092
0XFEED
1/2
which of these should work, in your opinion...?  (Python's own
opinion may differ!-)

I suspect that 'being a number' may be too vague a concept for
why 0j 'is a number' while 0k isn't, why 1e1 'is a number' while
0e0 or 1f1 aren't, why 3+2j 'is a number' while 3+2 or 3/2 aren't,
and ditto for a 'too-long' sequence of digits to fit in an int,
a digit-sequence with a leading 0 digit and a 9 somewhere, ...
(deeming that a complex, float, and/or long, is not "a number",
is fraught with just as many difficulties).

We _might_ have "just-checking" versions of every specific built-in
"factory-function", I guess.  For example, since
atoi('092')
works fine (and return 92) while
atoi('092',0)
throws a ValueError, we might systematically have a
wouldsucceedifyoutriedit
higher-order function...:
wouldsucceedifyoutriedit(atoi, '092')       # returns 1
wouldsucceedifyoutriedit(atoi, '092', 0)    # returns 0

It's actually a rather simple Python exercise to write this
higher-order function TODAY, e.g....:

def wouldsucceedifyoutriedit(function, *args):
try: return apply(function, args) or 1
except ValueError: return 0

Would it give significant added value to have it "built-in"?
I'm not sure, but I suspect it wouldn't.  It would, I guess,
encourage the traditional "look before you leap" approach...:

from string import atoi

if wouldsucceedifyoutriedit(function, *(str,)+otherargs):
return function(str, *otherargs)
else:
return default

rather than the more Pythonish "it's better to ask forgiveness
than permission" idiom...:

try: return function(str, *otherargs)
except ValueError: return default

I think the latter approach is what should be encouraged
instead -- it avoids duplication of operations, has more
general applicability, is actually simpler (once one gets
past the 'mental block' about deliberately trying some
operation that has good likelihood of failing...).

It _is_, of course, a matter of degrees -- we do, after
all, have "just-checking" versions of several operations
that _might_ be handled with appropriate try/except blocks
and/or default-values (hasattr, dict.has_key, ...).  But
here, since there is no single generic 'make this string
into a number of whatever numerical type it happens to
fit best', we'd have to keep genericity in terms of a
function-argument (and other potential arguments, see e.g.
the string.atoi case, where the second, optional argument
is an important indicator -- it gives the number-base...).

This nudges up the conceptual complexity of the "just
checking" case, and pushes down the performance of the
"look before you leap" approach; IMHO, the combined
effect is amply sufficient to suggest that, for this
case, we should encourage the more general and simpler
"it's better to ask forgiveness than permission" idiom.

Alex

```