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

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

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


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


当前回答

这个怎么样:

'3.14'.replace('.','',1).isdigit()

只有当有一个或没有“”时,它才会返回真在数字串中。

'3.14.5'.replace('.','',1).isdigit()

将返回false

编辑:刚刚看到另一条评论。。。可以为其他情况添加.replace(badstuff,“”,maxnum_badstuff)。如果你传递的是盐而不是任意的调味品(参考:xkcd#974),这会很好:P

其他回答

使用以下方法处理所有情况:-

import re
a=re.match('((\d+[\.]\d*$)|(\.)\d+$)' ,  '2.3') 
a=re.match('((\d+[\.]\d*$)|(\.)\d+$)' ,  '2.')
a=re.match('((\d+[\.]\d*$)|(\.)\d+$)' ,  '.3')
a=re.match('((\d+[\.]\d*$)|(\.)\d+$)' ,  '2.3sd')
a=re.match('((\d+[\.]\d*$)|(\.)\d+$)' ,  '2.3')

我做了一些速度测试。让我们假设,如果字符串可能是一个数字,则try/except策略是最快的。如果字符串不可能是数字,并且您对整数检查感兴趣,则值得进行一些测试(isdigit加上标题“-”)。如果您有兴趣检查浮点数,则必须使用try/except代码而不进行转义。

这篇文章已经有了很好的答案。我想给出一个稍微不同的观点。

我们可以对字母表进行否定搜索,而不是搜索数字、数字或浮点数。即,我们可以要求程序查看它是否不是字母表。

## Check whether it is not alpha rather than checking if it is digit
print(not "-1.2345".isalpha())
print(not "-1.2345e-10".isalpha())

如果你确定你的字符串是一个格式良好的数字(下面的条件1和条件2),它会很好地工作。但是,如果字符串错误地不是一个格式良好的数字,那么它将失败。在这种情况下,即使字符串不是有效的数字,它也会返回数字匹配。为了解决这种情况,必须有许多基于规则的方法。然而,此时此刻,我想起了正则表达式。以下是三个案例。请注意,正则表达式可以更好,因为我不是正则表达式专家。下面有两个列表:一个用于有效数字,一个用于无效数字。必须拾取有效数字,而不能拾取无效数字。

==条件1:确保字符串为有效数字,但未选择“inf”==

Valid_Numbers = ["1","-1","+1","0.0",".1","1.2345","-1.2345","+1.2345","1.2345e10","1.2345e-10","-1.2345e10","-1.2345E10","-inf"]
Invalid_Numbers = ["1.1.1","++1","--1","-1-1","1.23e10e5","--inf"]

################################ Condition 1: Valid number excludes 'inf' ####################################

Case_1_Positive_Result = list(map(lambda x: not x.isalpha(),Valid_Numbers))
print("The below must all be True")
print(Case_1_Positive_Result)

## This check assumes a valid number. So it fails for the negative cases and wrongly detects string as number
Case_1_Negative_Result = list(map(lambda x: not x.isalpha(),Invalid_Numbers))
print("The below must all be False")
print(Case_1_Negative_Result)
The below must all be True
[True, True, True, True, True, True, True, True, True, True, True, True, True]
The below must all be False
[True, True, True, True, True, True]

==条件2:确保字符串为有效数字,并选择“inf”==

################################ Condition 2: Valid number includes 'inf'  ###################################
Case_2_Positive_Result = list(map(lambda x: x=="inf" or not x.isalpha(),Valid_Numbers+["inf"]))
print("The below must all be True")
print(Case_2_Positive_Result)

## This check assumes a valid number. So it fails for the negative cases and wrongly detects string as number
Case_2_Negative_Result = list(map(lambda x: x=="inf" or not x.isalpha(),Invalid_Numbers+["++inf"]))
print("The below must all be False")
print(Case_2_Negative_Result)
The below must all be True
[True, True, True, True, True, True, True, True, True, True, True, True, True, True]
The below must all be False
[True, True, True, True, True, True, True]

==条件3:字符串不保证是有效数字==

import re
CompiledPattern = re.compile(r"([+-]?(inf){1}$)|([+-]?[0-9]*\.?[0-9]*$)|([+-]?[0-9]*\.?[0-9]*[eE]{1}[+-]?[0-9]*$)")
Case_3_Positive_Result = list(map(lambda x: True if CompiledPattern.match(x) else False,Valid_Numbers+["inf"]))
print("The below must all be True")
print(Case_3_Positive_Result)

## This check assumes a valid number. So it fails for the negative cases and wrongly detects string as number
Case_3_Negative_Result = list(map(lambda x: True if CompiledPattern.match(x) else False,Invalid_Numbers+["++inf"]))
print("The below must all be False")
print(Case_3_Negative_Result)
The below must all be True
[True, True, True, True, True, True, True, True, True, True, True, True, True, True]
The below must all be False
[False, False, False, False, False, False, False]

对于非数字字符串,请尝试:except:实际上比正则表达式慢。对于有效数字的字符串,正则表达式速度较慢。因此,适当的方法取决于您的输入。

如果您发现自己处于性能绑定中,可以使用名为fastnumbers的新第三方模块,该模块提供一个名为isfloat的函数。完全披露,我是作者。我已将其结果包含在以下时间中。


from __future__ import print_function
import timeit

prep_base = '''\
x = 'invalid'
y = '5402'
z = '4.754e3'
'''

prep_try_method = '''\
def is_number_try(val):
    try:
        float(val)
        return True
    except ValueError:
        return False

'''

prep_re_method = '''\
import re
float_match = re.compile(r'[-+]?\d*\.?\d+(?:[eE][-+]?\d+)?$').match
def is_number_re(val):
    return bool(float_match(val))

'''

fn_method = '''\
from fastnumbers import isfloat

'''

print('Try with non-number strings', timeit.timeit('is_number_try(x)',
    prep_base + prep_try_method), 'seconds')
print('Try with integer strings', timeit.timeit('is_number_try(y)',
    prep_base + prep_try_method), 'seconds')
print('Try with float strings', timeit.timeit('is_number_try(z)',
    prep_base + prep_try_method), 'seconds')
print()
print('Regex with non-number strings', timeit.timeit('is_number_re(x)',
    prep_base + prep_re_method), 'seconds')
print('Regex with integer strings', timeit.timeit('is_number_re(y)',
    prep_base + prep_re_method), 'seconds')
print('Regex with float strings', timeit.timeit('is_number_re(z)',
    prep_base + prep_re_method), 'seconds')
print()
print('fastnumbers with non-number strings', timeit.timeit('isfloat(x)',
    prep_base + 'from fastnumbers import isfloat'), 'seconds')
print('fastnumbers with integer strings', timeit.timeit('isfloat(y)',
    prep_base + 'from fastnumbers import isfloat'), 'seconds')
print('fastnumbers with float strings', timeit.timeit('isfloat(z)',
    prep_base + 'from fastnumbers import isfloat'), 'seconds')
print()

Try with non-number strings 2.39108395576 seconds
Try with integer strings 0.375686168671 seconds
Try with float strings 0.369210958481 seconds

Regex with non-number strings 0.748660802841 seconds
Regex with integer strings 1.02021503448 seconds
Regex with float strings 1.08564686775 seconds

fastnumbers with non-number strings 0.174362897873 seconds
fastnumbers with integer strings 0.179651021957 seconds
fastnumbers with float strings 0.20222902298 seconds

如你所见

try:except:对于数字输入很快,但对于无效输入很慢当输入无效时,正则表达式非常有效fastnumbers在这两种情况下都获胜

只有Mimic C#

在C#中,有两个不同的函数处理标量值的解析:

Float.Parse()Float.TryParse()

float.parse():

def parse(string):
    try:
        return float(string)
    except Exception:
        throw TypeError

注意:如果您想知道为什么我将异常更改为TypeError,请参阅以下文档。

float.try_parse():

def try_parse(string, fail=None):
    try:
        return float(string)
    except Exception:
        return fail;

注意:您不希望返回布尔值“False”,因为这仍然是一个值类型。没有更好的,因为它表明失败。当然,如果您想要一些不同的东西,可以将fail参数更改为您想要的任何值。

要扩展float以包含“parse()”和“try_parse()”,您需要对“float”类进行monkeypatch以添加这些方法。

如果你想尊重已有的函数,代码应该是这样的:

def monkey_patch():
    if(!hasattr(float, 'parse')):
        float.parse = parse
    if(!hasattr(float, 'try_parse')):
        float.try_parse = try_parse

侧注:我个人更喜欢称之为“猴子打拳”,因为我这样做时感觉就像在滥用语言,但YMMV除外。

用法:

float.parse('giggity') // throws TypeException
float.parse('54.3') // returns the scalar value 54.3
float.tryParse('twank') // returns None
float.tryParse('32.2') // returns the scalar value 32.2

伟大的蟒蛇圣人对罗马教廷夏皮索斯说:“你能做的任何事,我都能做得更好;我能做得比你更好。”