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

后端 未结 30 3913
暗喜
暗喜 2020-11-21 05:16

What is the best possible way to check if a string can be represented as a number in Python?

The function I currently have right now is:

def is_numb         


        
30条回答
  •  醉酒成梦
    2020-11-21 05:43

    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 False
    
    import 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 True
    
    
    def 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 timeit
    
    test_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_match
    from re import compile as re_compile
    
    def is_number_tryexcept(s):
        """ Returns True is string is a number. """
        try:
            float(s)
            return True
        except ValueError:
            return False
    
    def is_number_regex(s):
        """ Returns True is string is a number. """
        if re_match("^\d+?\.\d+?$", s) is None:
            return s.isdigit()
        return True
    
    
    comp = 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 True
    
    
    def is_number_repl_isdigit(s):
        """ Returns True is string is a number. """
        return s.replace('.','',1).isdigit()
    

提交回复
热议问题