Python:识别数字字符串?

Python:识别数字字符串?,python,regex,coercion,Python,Regex,Coercion,我尝试了几种方法,我真正关心的是性能,而不是正确性。我注意到基于regex的实现比使用类型强制的实现慢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) == Non

我尝试了几种方法,我真正关心的是性能,而不是正确性。我注意到基于regex的实现比使用类型强制的实现慢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

谢谢

不太可能。强迫是一种公认的方法。

不太可能。强迫是公认的方式。首先,他们做的不是同一件事。例如,可以将float指定为1e3,float将接受该值。这也不是,而是转换

其次,不要在IsNumber2中导入re,尤其是当您试图将它与timeit一起使用时。在函数外部执行导入

最后,浮动速度更快并不奇怪。这是一个用C编写的专用例程,用于非常特定的目的,而正则表达式必须转换为可解释的形式


你的第一个版本,使用float,足够快吗?应该是这样的,我不知道有什么更好的方法可以在Python中做同样的事情。

首先,他们做的不是同样的事情。例如,可以将float指定为1e3,float将接受该值。这也不是,而是转换

其次,不要在IsNumber2中导入re,尤其是当您试图将它与timeit一起使用时。在函数外部执行导入

最后,浮动速度更快并不奇怪。这是一个用C编写的专用例程,用于非常特定的目的,而正则表达式必须转换为可解释的形式


你的第一个版本,使用float,足够快吗?应该是这样的,我不知道有什么更好的方法可以在Python中完成同样的事情。

您可以先尝试编译正则表达式,但我想它仍然会更慢


另外,如果你想知道你的字符串是否是一个数字,因为你要用它进行计算,你必须强制它

您可以先尝试编译正则表达式,但我想还是会比较慢


另外,如果你想知道你的字符串是否是一个数字,因为你要用它进行计算,你必须强制它

答案在很大程度上取决于“数字字符串”的含义。如果您对数字字符串的定义是“float接受的任何内容”,那么很难改进try-except方法

但请记住,float可能比您希望的更自由:在大多数机器上,它将接受表示无穷大和N的字符串。在我的机器上,它接受“nandead!”$例如,鹦鹉。它还将接受前导空格和尾随空格。根据应用程序的不同,您可能希望排除浮点的指数表示。在这些情况下,使用正则表达式是有意义的。要仅排除无穷大和nan,使用try-except方法,然后使用math.isnan和math.isinf检查转换结果可能会更快

为数字字符串编写正确的正则表达式是一项非常容易出错的任务。例如,IsNumber2函数接受字符串“.”。您可以在decimal模块源代码中找到经过战斗测试的数字字符串正则表达式版本。下面是一些小的编辑:

_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所接受的内容,除了前导和尾随的空格以及NaN的一些细微差别,用于发送NaN信号的额外“s”以及诊断信息。当我需要一个数字正则表达式时,我通常从这个正则表达式开始,编辑掉我不需要的位


注意:可以想象,float可能比regex慢,因为它不仅要解析字符串,还要将其转换为float,这是一个相当复杂的计算过程;如果是的话,这仍然是一个惊喜。

答案在很大程度上取决于你所说的“数字字符串”是什么意思。如果您对数字字符串的定义是“float接受的任何内容”,那么很难改进try-except方法

但请记住,float可能比您希望的更自由:在大多数机器上,它将接受表示无穷大和N的字符串。在我的机器上,它接受“nandead!”$例如,鹦鹉。它还将接受前导空格和尾随空格。根据应用程序的不同,您可能希望排除浮点的指数表示。在这些情况下,使用正则表达式是有意义的。要仅排除无穷大和nan,使用try-except方法,然后使用math.isnan和math.isinf检查转换结果可能会更快

为数字字符串编写正确的正则表达式是一项非常容易出错的任务。例如,IsNumber2函数接受字符串“.”。您可以在decimal模块源代码中找到经过战斗测试的数字字符串正则表达式版本。下面是一些小的编辑:

_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所接受的几乎完全匹配,除了前导和尾随的空格,以及NaN的一些细微差别,额外的“s”表示NaN, 以及诊断信息。当我需要一个数字正则表达式时,我通常从这个正则表达式开始,编辑掉我不需要的位



注意:可以想象,float可能比regex慢,因为它不仅要解析字符串,还要将其转换为float,这是一个相当复杂的计算过程;不过,如果真是这样的话,那还是会令人惊讶的。

是的,你的方法看起来相当不错。我一点也不惊讶正则表达式方法的速度较慢。一方面,它是在函数内部导入re。@贾斯汀:第二次导入re只是从sys.modules复制引用的问题。缓慢的部分是每次编译regex.import语句都会执行一些不需要的锁定。这是更快地让他们远离功能。谢谢!将导入移到外部确实会改变一些情况,但与其他函数相比,它仍然非常慢。是的,您的方法看起来相当不错。我一点也不惊讶正则表达式方法的速度较慢。一方面,它是在函数内部导入re。@贾斯汀:第二次导入re只是从sys.modules复制引用的问题。缓慢的部分是每次编译regex.import语句都会执行一些不需要的锁定。这是更快地让他们远离功能。谢谢!将导入移到外部确实会稍微改变一些事情,但与其他函数相比,它仍然非常慢。编译的影响很小,它们是缓存的。编译的影响很小,它们是缓存的。第一种方法是正确和有用的。第二个是间接的,有许多微妙的错误。@Mike Graham:你的评论听起来像是一个答案。请删除评论,发布答案,我们可以正确地更新它。你的正则表达式中的另一个错误:你需要避开它。在那之前?除非您希望123z45被视为一个数字。此外,使用单个反斜杠在非原始字符串中进行正则表达式转义是一种不好的形式,尽管在这种情况下它恰好起作用。说出\\d或使用原始字符串。第一种方法正确且有用。第二个是间接的,有许多微妙的错误。@Mike Graham:你的评论听起来像是一个答案。请删除评论,发布答案,我们可以正确地更新它。你的正则表达式中的另一个错误:你需要避开它。在那之前?除非您希望123z45被视为一个数字。此外,使用单个反斜杠在非原始字符串中进行正则表达式转义是一种不好的形式,尽管在这种情况下它恰好起作用。要么说\\d,要么使用原始字符串。我想第一个版本足够快了,我只是好奇而已。谢谢我想第一个版本足够快了,我只是好奇而已。谢谢