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

Alex Martelli aleaxit at yahoo.com
Sun Nov 5 18:29:37 CET 2000


"Gaute B Strokkenes" <gs234 at cam.ac.uk> wrote in message
news:4a8zqyqxqv.fsf at kern.srcf.societies.cam.ac.uk...
    [snip]
> def isanum(str):
>     # FIXME: Surely there must be a sane way of doing this.
>     from string import find, digits
>     for i in range(len(str)):
>         if find(digits, str[i]) == -1:
>             return 0
>     return 1

There are many ways to check if all characters in the
string are digits -- which is NOT necessarily the same
as checking whether the string represents a valid
"number", depending on what exactly one means --
the following strings:
    -1
    1.0
    99999999999999999999L
    1.23e4
    1+2j
all represent valid Python numbers of some kind or
other, but none of them is made up just of digits.
OTOH, the string:
    99999999999999999999
is not a valid numeric representation in Python (it's
too large as an int, lacks a trailing L as a long),
despite being made up just of digits.


The simplest way to check if a string is made up
just of digits is probably via the re module...:

def isanum(str):
    import re
    return re.match(r'\d*',str)!=None

this checks for '0 or more digits', like your original
code -- i.e., an empty str will get a 1 return value.

To check for '1 or more digits', just change the
regular expression rawstring to r'\d+'.


If one doesn't want to use re for whatever
reason, then looping as you did is probably
next-best, though it can be done a bit better,
e.g.:

def isanum(str):
    from string import digits
    for c in str:
        if not c in digits: return 0
    return 1

i.e., you can loop over elements of the sequence
(characters) directly, and use the direct test in
Python (the 'c in digits' part) rather than the
string.find function.

Another peculiar-looking variation:

def isanum(str):
    from string import digits
    return not -1 in map(digits.find,str)

this always and implicitly loops all through str,
applying to each item (character) the digits.find
bound-method; if any of the items in the result
list is -1 (i.e., '-1 in' the resultlist), then this
yields 0 as the returnvalue, else 1.

The list-comprehension equivalent:

def isanum(str):
    from string import digits
    return not -1 in [digits.find(c) for c in str]

or, eschewing .find:

def isanum(str):
    from string import digits
    return not 0 in [(c in digits) for c in str]

or, moving the test inside the comprehension
and turning it around:

def isanum(str):
    from string import digits
    return [] == [c for c in str if not c in digits]


Are these 'sane'...?  Nah.  re.match is really the
only one worth thinking of for this specific case!

But it's fun to think of alternatives, and they're
worth keeping in mind for other, similar tasks in
which re would become bothersome... (plus, one
can show off, "look, ma, no re!":-).


Alex






More information about the Python-list mailing list