How do I check if a string is a number (float)? How do I check if a string is a number (float)? python python

How do I check if a string is a number (float)?


In case you are looking for parsing (positive, unsigned) integers instead of floats, you can use the isdigit() function for string objects.

>>> a = "03523">>> a.isdigit()True>>> b = "963spam">>> b.isdigit()False

String Methods - isdigit(): Python2, Python3

There's also something on Unicode strings, which I'm not too familiar withUnicode - Is decimal/decimal


Which, not only is ugly and slow

I'd dispute both.

A regex or other string parsing method would be uglier and slower.

I'm not sure that anything much could be faster than the above. It calls the function and returns. Try/Catch doesn't introduce much overhead because the most common exception is caught without an extensive search of stack frames.

The issue is that any numeric conversion function has two kinds of results

  • A number, if the number is valid
  • A status code (e.g., via errno) or exception to show that no valid number could be parsed.

C (as an example) hacks around this a number of ways. Python lays it out clearly and explicitly.

I think your code for doing this is perfect.


TL;DR The best solution is s.replace('.','',1).isdigit()

I did some benchmarks comparing the different approaches

def is_number_tryexcept(s):    """ Returns True is string is a number. """    try:        float(s)        return True    except ValueError:        return Falseimport re    def is_number_regex(s):    """ Returns True is string is a number. """    if re.match("^\d+?\.\d+?$", s) is None:        return s.isdigit()    return Truedef is_number_repl_isdigit(s):    """ Returns True is string is a number. """    return s.replace('.','',1).isdigit()

If the string is not a number, the except-block is quite slow. But more importantly, the try-except method is the only approach that handles scientific notations correctly.

funcs = [          is_number_tryexcept,           is_number_regex,          is_number_repl_isdigit          ]a_float = '.1234'print('Float notation ".1234" is not supported by:')for f in funcs:    if not f(a_float):        print('\t -', f.__name__)

Float notation ".1234" is not supported by:
- is_number_regex

scientific1 = '1.000000e+50'scientific2 = '1e50'print('Scientific notation "1.000000e+50" is not supported by:')for f in funcs:    if not f(scientific1):        print('\t -', f.__name__)print('Scientific notation "1e50" is not supported by:')for f in funcs:    if not f(scientific2):        print('\t -', f.__name__)

Scientific notation "1.000000e+50" is not supported by:
- is_number_regex
- is_number_repl_isdigit
Scientific notation "1e50" is not supported by:
- is_number_regex
- is_number_repl_isdigit

EDIT: The benchmark results

import timeittest_cases = ['1.12345', '1.12.345', 'abc12345', '12345']times_n = {f.__name__:[] for f in funcs}for t in test_cases:    for f in funcs:        f = f.__name__        times_n[f].append(min(timeit.Timer('%s(t)' %f,                       'from __main__ import %s, t' %f)                              .repeat(repeat=3, number=1000000)))

where the following functions were tested

from re import match as re_matchfrom re import compile as re_compiledef is_number_tryexcept(s):    """ Returns True is string is a number. """    try:        float(s)        return True    except ValueError:        return Falsedef is_number_regex(s):    """ Returns True is string is a number. """    if re_match("^\d+?\.\d+?$", s) is None:        return s.isdigit()    return Truecomp = re_compile("^\d+?\.\d+?$")    def compiled_regex(s):    """ Returns True is string is a number. """    if comp.match(s) is None:        return s.isdigit()    return Truedef is_number_repl_isdigit(s):    """ Returns True is string is a number. """    return s.replace('.','',1).isdigit()

enter image description here