我尝试了几种方法,我真的只关心性能,而不是正确性。我注意到基于正则表达式的实现比使用类型强制的实现慢约3-4倍。还有另一种更有效的方法吗?
def IsNumber(x):
try:
_ = float(x)
except ValueError:
return False
return True
def IsNumber2(x):
import re
if re.match("^\d*.?\d*$", x) == None:
return False
return True
谢谢!
答案 0 :(得分:6)
首先,他们没有做同样的事情。例如,浮点数可以指定为“1e3”,而float()将接受它。它也不是coercion,而是转换。
其次,不要在IsNumber2中导入re,特别是如果你试图将它与timeit一起使用。在函数外部进行导入。
最后,float()更快,我并不感到惊讶。它是一个用C编写的专用例程,用于非常特定的目的,而正则表达式必须转换为一个被解释的形式。
你的第一个版本,使用float(),足够快吗?应该是,而且我不知道在Python中做同样事情的更好方法。
答案 1 :(得分:2)
不是真的。强制是公认的做法。
答案 2 :(得分:2)
答案很大程度上取决于“数字字符串”的含义。如果你对数字字符串的定义是'浮动接受的任何东西',那么很难改进try-except方法。
但请记住,浮动可能比你想要的更自由:在大多数机器上,它会接受代表无穷大和无限的字符串。例如,在我的机器上,它接受'nan(dead!$#parrot)'
。它还将接受前导和尾随空格。根据您的应用程序,您可能希望排除浮点数的指数表示。在这些情况下,使用正则表达式是有意义的。要排除无穷大和无穷大,使用try-except方法可能会更快,然后使用math.isnan和math.isinf来检查转换结果。
为数字字符串编写正确的正则表达式是一个令人惊讶的容易出错的任务。例如,您的IsNumber2
函数接受字符串'.'
。您可以在十进制模块源中找到经过实战测试的数字字符串正则表达式版本。这是(有一些小编辑):
_parser = re.compile(r""" # A numeric string consists of:
(?P<sign>[-+])? # an optional sign, followed by either...
(
(?=\d|\.\d) # ...a number (with at least one digit)
(?P<int>\d*) # having a (possibly empty) integer part
(\.(?P<frac>\d*))? # followed by an optional fractional part
(E(?P<exp>[-+]?\d+))? # followed by an optional exponent, or...
|
Inf(inity)? # ...an infinity, or...
|
(?P<signal>s)? # ...an (optionally signaling)
NaN # NaN
(?P<diag>\d*) # with (possibly empty) diagnostic info.
)
\Z
""", re.VERBOSE | re.IGNORECASE | re.UNICODE).match
这几乎与float接受的完全匹配,除了前导和尾随空格以及nans的一些细微差别(信号nans的额外's'和诊断信息)。当我需要一个数字正则表达式时,我通常从这个开始,然后编辑出我不需要的位。
N.B。它是可以想象的浮点数可能比正则表达式慢,因为它不仅要解析字符串,还要把它变成浮点数,这是一个非常复杂的计算;不过,如果它仍然是一个惊喜。
答案 3 :(得分:0)
你可能会先尝试编译你的正则表达式,但我想它仍会慢一些。
另外,如果你想知道你的字符串是否是一个数字,因为你要用它进行计算,你无论如何都要强制它。