如何在Python中检查字符串是否表示数值?

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

上述方法可行,但似乎很笨拙。


如果您正在测试的内容来自用户输入,那么即使它表示int或float,它仍然是一个字符串。请参阅如何将输入读取为数字?用于转换输入,并询问用户输入,直到他们给出有效响应以确保输入在继续之前表示int或float(或其他要求)。


当前回答

我知道我参加晚会迟到了,但我想出了一个不在这里的解决方案:此解决方案遵循Python中的EAFP原则

def get_number_from_string(value):
    try:
        int_value = int(value)
        return int_value

    except ValueError:
        return float(value)

说明:

如果字符串中的值是一个浮点数,并且我首先尝试将其解析为一个int,那么它将抛出一个ValueError。因此,我捕捉到该错误,并将该值解析为float和return。

其他回答

因此,将所有这些放在一起,检查Nan、无穷大和复数(看起来它们是用j指定的,而不是i,即1+2j),结果是:

def is_number(s):
    try:
        n=str(float(s))
        if n == "nan" or n=="inf" or n=="-inf" : return False
    except ValueError:
        try:
            complex(s) # for complex
        except ValueError:
            return False
    return True

我想看看哪种方法最快。总的来说,check_replace函数给出了最佳和最一致的结果。check_exception函数给出了最快的结果,但前提是没有触发异常——这意味着它的代码是最有效的,但抛出异常的开销非常大。

请注意,检查成功的强制转换是唯一准确的方法,例如,这与check_exception一起工作,但其他两个测试函数将为有效的float返回False:

huge_number = float('1e+100')

以下是基准代码:

import time, re, random, string

ITERATIONS = 10000000

class Timer:    
    def __enter__(self):
        self.start = time.clock()
        return self
    def __exit__(self, *args):
        self.end = time.clock()
        self.interval = self.end - self.start

def check_regexp(x):
    return re.compile("^\d*\.?\d*$").match(x) is not None

def check_replace(x):
    return x.replace('.','',1).isdigit()

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

to_check = [check_regexp, check_replace, check_exception]

print('preparing data...')
good_numbers = [
    str(random.random() / random.random()) 
    for x in range(ITERATIONS)]

bad_numbers = ['.' + x for x in good_numbers]

strings = [
    ''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(random.randint(1,10)))
    for x in range(ITERATIONS)]

print('running test...')
for func in to_check:
    with Timer() as t:
        for x in good_numbers:
            res = func(x)
    print('%s with good floats: %s' % (func.__name__, t.interval))
    with Timer() as t:
        for x in bad_numbers:
            res = func(x)
    print('%s with bad floats: %s' % (func.__name__, t.interval))
    with Timer() as t:
        for x in strings:
            res = func(x)
    print('%s with strings: %s' % (func.__name__, t.interval))

以下是2017年MacBook Pro 13上Python 2.7.10的结果:

check_regexp with good floats: 12.688639
check_regexp with bad floats: 11.624862
check_regexp with strings: 11.349414
check_replace with good floats: 4.419841
check_replace with bad floats: 4.294909
check_replace with strings: 4.086358
check_exception with good floats: 3.276668
check_exception with bad floats: 13.843092
check_exception with strings: 15.786169

以下是2017年MacBook Pro 13上Python 3.6.5的结果:

check_regexp with good floats: 13.472906000000009
check_regexp with bad floats: 12.977665000000016
check_regexp with strings: 12.417542999999995
check_replace with good floats: 6.011045999999993
check_replace with bad floats: 4.849356
check_replace with strings: 4.282754000000011
check_exception with good floats: 6.039081999999979
check_exception with bad floats: 9.322753000000006
check_exception with strings: 9.952595000000002

以下是2017年MacBook Pro 13上PyPy 2.7.13的结果:

check_regexp with good floats: 2.693217
check_regexp with bad floats: 2.744819
check_regexp with strings: 2.532414
check_replace with good floats: 0.604367
check_replace with bad floats: 0.538169
check_replace with strings: 0.598664
check_exception with good floats: 1.944103
check_exception with bad floats: 2.449182
check_exception with strings: 2.200056

str.inumeric()

如果字符串中的所有字符都是数字字符,则返回True,并且至少有一个字符,否则为False。数字字符包括数字字符Unicode数值属性,例如U+2155,VULGAR FRACTION ONE第五。形式上,数字字符是具有属性值的字符Numeric_Type=数字,Numeric_Type=十进制或Numeric_Type=数字。

str.isdecimal()

如果字符串中的所有字符都是十进制字符,并且至少有一个字符,否则为False。十进制字符是可用于在基数10中形成数字的那些,阿拉伯数字零。形式上,十进制字符是一个字符在Unicode通用类别“Nd”中。

两者都适用于Python 3.0中的字符串类型。

RyanN建议

若要为NaN和Inf返回False,请将行更改为x=float;返回(x==x)和(x-1!=x)。对于除Inf和NaN之外的所有浮点值,这都应返回True

但这并不完全有效,因为对于足够大的浮点数,x-1==x返回true。例如,2.0**54-1==2.0**54

这是我的简单方法。假设我在循环一些字符串,如果它们变成数字,我想将它们添加到数组中。

try:
    myvar.append( float(string_to_check) )
except:
    continue

如果myvar.apppend是一个数字,则将其替换为要对字符串执行的任何操作。其想法是尝试使用float()操作,并使用返回的错误来确定字符串是否为数字。