协慌网

登录 贡献 社区

如何检查字符串是否为数字(浮点数)?

检查字符串是否可以在 Python 中表示为数字的最佳方法是什么?

我目前拥有的功能是:

def is_number(s):
    try:
        float(s)
        return True
    except ValueError:
        return False

这不仅是丑陋而且缓慢,似乎很笨重。但是我没有找到更好的方法,因为在 main 函数中调用float更糟糕。

答案

如果您正在寻找解析(正,无符号)整数而不是浮点数,则可以对字符串对象使用isdigit()函数。

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

字符串方法 - isdigit()

在 Unicode 字符串上也有一些东西,我对 Unicode 不太熟悉- 是十进制 / 十进制

其中,不仅是丑陋而且缓慢

我两个都有争议。

正则表达式或其他字符串解析将更加丑陋和缓慢。

我不确定任何事情都可能比上面更快。它调用函数并返回。 Try / Catch 不会引入太多开销,因为最常见的异常是在没有大量搜索堆栈帧的情况下捕获的。

问题是任何数字转换函数都有两种结果

  • 如果数字有效,则为数字
  • 状态代码(例如,通过 errno)或异常以显示无法解析有效数字。

C(作为一个例子)以多种方式解决这个问题。 Python 明确而明确地阐述了它。

我认为你这样做的代码是完美的。

TL; DR最好的解决方案是s.replace('.','',1).isdigit()

我做了一些比较不同方法的基准

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()

如果字符串不是数字,则 except-block 非常慢。但更重要的是,try-except 方法是正确处理科学记数法的唯一方法。

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__)

不支持浮动符号 “.1234”:
- 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__)

不支持科学记数法 “1.000000e + 50”:
- is_number_regex
- is_number_repl_isdigit
不支持科学记数法 “1e50”:
- is_number_regex
- is_number_repl_isdigit

编辑:基准测试结果

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)))

测试以下功能的地方

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()

在此输入图像描述