如何检查字符串是否表示一个数字(浮点数或整数)?
我怎么检查一个字符串在Python中是否表示一个数字?
def is_number(s):
try:
float(s)
return True
except ValueError:
return False
上面的做法可以,但感觉有点笨重。
如果你测试的内容来自用户输入,即使它看起来像一个数字,它仍然是一个字符串。想了解如何把输入转换成数字,可以查看如何将输入读取为数字?,而如果你想确保用户输入的是有效的数字,可以参考让用户输入直到他们给出有效的响应,这样可以确保输入的是一个整数或浮点数(或者其他要求)后再继续。
41 个回答
总结 最好的解决方案是 s.replace('.','',1).isdigit()
我做了一些 基准测试,比较了不同的方法
def is_number_tryexcept(s):
""" Returns True if string is a number. """
try:
float(s)
return True
except ValueError:
return False
import re
def is_number_regex(s):
""" Returns True if 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 if string is a number. """
return s.replace('.','',1).isdigit()
如果字符串不是一个数字,异常处理的部分会比较慢。但更重要的是,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
科学计数法示例1 = '1.000000e+50'
科学计数法示例2 = '1e50'
打印('科学计数法 "1.000000e+50" 不被以下方法支持:')
对于每个方法:
如果这个方法不支持科学计数法示例1:
打印('\t -', 方法.名称)
打印('科学计数法 "1e50" 不被以下方法支持:')
对于每个方法:
如果这个方法不支持科学计数法示例2:
打印('\t -', 方法.名称)
科学计数法 "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 if string is a number. """
try:
float(s)
return True
except ValueError:
return False
def is_number_regex(s):
""" Returns True if 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 if string is a number. """
if comp.match(s) is None:
return s.isdigit()
return True
def is_number_repl_isdigit(s):
""" Returns True if string is a number. """
return s.replace('.','',1).isdigit()
对于非负整数(也就是不带负号的整数),可以使用 isdigit()
这个方法:
>>> a = "03523"
>>> a.isdigit()
True
>>> b = "963spam"
>>> b.isdigit()
False
isdigit()
的文档说明可以在这里找到: Python2, Python3
如果你在使用 Python 2 的 Unicode 字符串,可以用 isnumeric()
这个方法。
这不仅看起来丑,而且速度慢。
我对此有不同的看法。
用正则表达式或者其他字符串解析方法会更丑也更慢。
我不太确定还有什么比上面的方法更快。它只是调用一个函数然后返回。使用尝试/捕获(Try/Catch)并不会增加太多负担,因为最常见的异常是直接捕获的,不需要在堆栈帧中进行复杂的搜索。
问题在于,任何数字转换函数都有两种结果:
- 如果数字有效,就返回一个数字。
- 如果没有有效的数字可以解析,就返回一个状态码(比如通过errno)或者抛出一个异常。
以C语言为例,它有很多方法来处理这个问题。而Python则清晰明确地展示了这一点。
我觉得你写的代码做得很好。