如何检查字符串是否为数字(浮点数)?

Dan*_*erg 1519 python floating-point casting type-conversion

检查字符串是否可以在Python中表示为数字的最佳方法是什么?

我目前拥有的功能是:

def is_number(s):
    try:
        float(s)
        return True
    except ValueError:
        return False
Run Code Online (Sandbox Code Playgroud)

这不仅是丑陋而且缓慢,似乎很笨重.但是我没有找到更好的方法,因为调用floatmain函数更糟糕.

Zoo*_*tor 1538

如果您正在寻找解析(正,无符号)整数而不是浮点数,则可以将该isdigit()函数用于字符串对象.

>>> a = "03523"
>>> a.isdigit()
True
>>> b = "963spam"
>>> b.isdigit()
False
Run Code Online (Sandbox Code Playgroud)

字符串方法 -​​ isdigit()

在Unicode字符串上也有一些东西,我对Unicode不太熟悉 - 是十进制/十进制

  • 这对负面也是负面的 (229认同)
  • 它也不适用于带小数位数的数字,如1.2 (215认同)
  • 但是,这对十六进制不起作用. (77认同)
  • 虽然Number!= Digit,但是正在寻找测试字符串是否包含整数的方法的人可能会很好地发现这个问题,并且isDigit方法可能非常适合他们的应用程序. (35认同)
  • 失败的指数也是:'1e3'.isdigit() - > False (20认同)
  • @AdamParkin:`isdigit()`和`int()`对于什么是整数有不同的看法,例如,对于Unicode字符[`u'\ u00b9'`](http://codepoints.net/U+00B9) :`u'¹'.isdigit()`是'True`但是`int(u'¹')`引发了ValueError. (8认同)
  • +1:isdigit()可能不是OP正在寻找的东西,但它正是我想要的.可能不是这种答案和方法不涵盖所有类型的数字,但它仍然高度相关,与其准确性的争论相反.虽然"数字!=数字",但数字仍然是数字的子集,特别是正数,非负数,并使用1-10.此外,对于您要检查字符串是否为数字ID的情况,此方法特别有用且简洁,这通常属于我刚才描述的数字子集. (6认同)
  • +1,我正在寻找基于我的谷歌查询的这个解决方案,所以任何人说这个答案是无关紧要的是没有考虑任何人除了OP.由于堆栈溢出有如此多的答案显示在谷歌,这与那些正在寻找此类解决方案的人绝对相关(如果你需要删除电话号码中的任何非数字:`phone =''.join ([n在someString中为n,如果n.isdigit()])`) (4认同)
  • 即使这个答案没有解决OP的问题,为了解决浮点数的问题,做一些像a.isdigit()或a.replace('.','').isdigit()? (3认同)
  • 名称`isdigit`从一开始就具有误导性,因为数字意味着`[0-9]` (3认同)
  • @JustinJohnson:你读过我的[之前的评论](http://stackoverflow.com/questions/354038/how-do-i-check-if-a-string-is-a-number-in-python#comment18339463_354073) ? 你可能想要 [`isdecimal()` 代替](http://stackoverflow.com/a/22793379/4279)。 (2认同)
  • @JFSebastian你是对的;`isdecimal()` 是在我描述的场景中使用的正确方法。 (2认同)
  • 当它完全错误时,它有800多个upvotes?事实上,这里的评论就像"+1,这不回答问题,但无论如何帮助我"让我大吃一惊.** - **1. (2认同)

S.L*_*ott 663

其中,不仅是丑陋而且缓慢

我两个都有争议.

正则表达式或其他字符串解析将更加丑陋和缓慢.

我不确定任何事情都可能比上面更快.它调用函数并返回.Try/Catch不会引入太多开销,因为最常见的异常是在没有大量搜索堆栈帧的情况下捕获的.

问题是任何数字转换函数都有两种结果

  • 如果数字有效,则为数字
  • 状态代码(例如,通过errno)或异常以显示无法解析有效数字.

C(作为一个例子)以多种方式解决这个问题.Python明确而明确地阐述了它.

我认为你这样做的代码是完美的.

  • 我不认为代码是完美的(但我认为它非常接近):更常见的是将*only*部分在`try`子句中"测试",所以我会把`return True`在`try`的`else`子句中.其中一个原因是,问题中的代码,如果我必须检查它,我将不得不检查`try`子句中的第二个语句不能引发ValueError:授予,这不需要太多时间或脑力,但为什么在不需要任何东西时使用? (19认同)
  • 但抽象是图书馆的重点.拥有'isNumber'函数(使用任何语言)有很大的帮助,因为你可以将它直接构建到if语句中,并且具有更多可读和可维护的代码,这些代码依赖于try-catch块.此外,如果您需要在多个类/模块中多次使用代码,那么您使用的代码行数比内置函数要多. (9认同)
  • 真可怕.怎么样,如果我不在乎数字_I_只是它是一个数字(这是什么把我带到这里)?而不是一行`IsNumeric()`我最终得到一个try/catch或另一个包装try/catch.啊 (7认同)
  • 它没有提供"开箱即用",因为`if is_number(s):x = float(x)else:// fail`与`try:x = float(x)catch TypeError的代码行数相同:#fail`.这个实用功能是一个完全不必要的抽象. (4认同)
  • 答案似乎很有吸引力,但让我想知道为什么它没有提供开箱即用......我会复制它并在任何情况下使用它. (3认同)
  • @Basic我不明白你的观点.命名你的函数,它检查`IsNumeric`并使用该函数.这就是使用功能的想法 - 拥有单行. (2认同)
  • @Nils我的观点是,在我使用的其他所有高级语言中都可以使用这种明显,简单的操作,它的缺失感觉就像一个明显的遗漏.再说一次,这不是一个长时间讨论的地方,所以让我们同意不同意. (2认同)

小智 139

TL; DR最好的解决方案是s.replace('.','',1).isdigit()

我做了一些比较不同方法的基准

def is_number_tryexcept(s):
    """ Returns True is string is a number. """
    try:
        float(s)
        return True
    except ValueError:
        return False

import re    
def is_number_regex(s):
    """ Returns True is 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 is string is a number. """
    return s.replace('.','',1).isdigit()
Run Code Online (Sandbox Code Playgroud)

如果字符串不是数字,则except-block非常慢.但更重要的是,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__)
Run Code Online (Sandbox Code Playgroud)

以下不支持浮点表示法".1234":
- is_number_regex

scientific1 = '1.000000e+50'
scientific2 = '1e50'


print('Scientific notation "1.000000e+50" is not supported by:')
for f in funcs:
    if not f(scientific1):
        print('\t -', f.__name__)




print('Scientific notation "1e50" is not supported by:')
for f in funcs:
    if not f(scientific2):
        print('\t -', f.__name__)
Run Code Online (Sandbox Code Playgroud)

不支持科学计数法"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)))
Run Code Online (Sandbox Code Playgroud)

测试以下功能的地方

from re import match as re_match
from re import compile as re_compile

def is_number_tryexcept(s):
    """ Returns True is string is a number. """
    try:
        float(s)
        return True
    except ValueError:
        return False

def is_number_regex(s):
    """ Returns True is 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 is string is a number. """
    if comp.match(s) is None:
        return s.isdigit()
    return True


def is_number_repl_isdigit(s):
    """ Returns True is string is a number. """
    return s.replace('.','',1).isdigit()
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

  • 好的图表+1.我看到了基准测试和锯图,所有TL; DR事情变得清晰直观. (11认同)
  • **太棒了,**除了求幂和负数的错误否定的明显警告之外——您可以通过链接 `s.replace()` 调用来轻松纠正。例如,`s.replace('.','',1).replace('e-','',1).replace('e','',1).isdigit()`处理幂运算。要处理负数,只需向左删除第一个字符(如果是破折号)。例如,`s.lstrip('-').replace('.','',1).replace('e-','',1).replace('e','',1)。 isdigit()`。*是的,我已经彻底测试了该单行代码,并可以确认它的行为符合预期。* (8认同)
  • 此方法不处理负数(破折号)。我主张只使用float方法,因为它不太容易出错,并且每次都会起作用。 (7认同)
  • 需要注意的重要一点是,即使假设不能有破折号,replace-isdigit 方法也只是对于非数字(错误结果)更快,而 try-except 方法对于数字(真实结果)更快。如果您的大部分输入都是有效输入,那么最好使用 try-except 解决方案! (5认同)
  • 不适用于“1.5e-9”等指数表示法或负数。 (2认同)

gvr*_*cha 67

您可能需要考虑一个例外:字符串'NaN'

如果你想让is_number为'NaN'返回FALSE,那么这段代码将不起作用,因为Python将它转换为一个不是数字的数字的表示(谈论身份问题):

>>> float('NaN')
nan
Run Code Online (Sandbox Code Playgroud)

否则,我实际上应该感谢你现在广泛使用的代码片段.:)

G.

  • 另一个例外是字符串''inf'.`inf`或`NaN`也可以用`+`或`-`作为前缀,但仍然可以接受. (7认同)
  • 对于小于`inf`的大浮点数,`x-1 == x`为真.从Python 3.2开始,您可以使用`math.isfinite`来测试既不是NaN也不是无限的数字,或者在此之前检查`math.isnan`和`math.isinf`. (5认同)
  • 如果要为NaN和Inf返回False,请将行更改为x = float(s); return(x == x)和(x - 1!= x).对于除Inf和NaN之外的所有浮点数,这应该返回True (4认同)
  • 实际上,如果传递的文本实际上不是数字的表示,那么"NaN"可能是一个很好的返回值(而不是"False").检查它是一种痛苦(Python的`float`类型确实需要一种方法)但你可以在计算中使用它而不会产生错误,只需要检查结果. (2认同)

小智 54

这个怎么样:

'3.14'.replace('.','',1).isdigit()
Run Code Online (Sandbox Code Playgroud)

只有在有'或'的情况下才会返回true.在数字串中.

'3.14.5'.replace('.','',1).isdigit()
Run Code Online (Sandbox Code Playgroud)

将返回false

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

  • 然而,这并不能解释负数. (7认同)
  • 或者带有指数的数字,如"1.234e56"(也可能写成"+ 1.234E + 56"和更多变体). (5认同)

Mat*_*son 40

Alfe指出您不需要单独检查浮动,因为复杂处理两者:

def is_number(s):
    try:
        complex(s) # for int, long, float and complex
    except ValueError:
        return False

    return True
Run Code Online (Sandbox Code Playgroud)

之前说过:在一些罕见的情况下,您可能还需要检查复数(例如1 + 2i),这不能用浮点数表示:

def is_number(s):
    try:
        float(s) # for int, long and float
    except ValueError:
        try:
            complex(s) # for complex
        except ValueError:
            return False

    return True
Run Code Online (Sandbox Code Playgroud)

  • 我不同意.在正常使用中这是非常不可能的,并且当你使用它们时,你会更好地构建一个is_complex_number()调用,而不是用额外的操作来调用0.0001%的误操作机会. (14认同)
  • 你可以完全剥离`float()`东西,然后检查`complex()`调用是否成功.由`float()`解析的所有东西都可以用`complex()`来解析. (3认同)

Jas*_*ker 38

这不仅是丑陋而且缓慢,似乎很笨重.

这可能需要一些时间来习惯,但这是做到这一点的pythonic方式.正如已经指出的那样,替代方案更糟糕.但是以这种方式做事还有另一个好处:多态性.

鸭子打字背后的核心理念是"如果它像鸭子一样走路和说话,那么它就是一只鸭子." 如果您决定需要子类化字符串以便可以更改确定是否可以将某些内容转换为浮点数的方式,该怎么办?或者如果您决定完全测试其他对象怎么办?您无需更改上述代码即可完成这些操作.

其他语言通过使用接口解决了这些问题.我将保存分析哪个解决方案更适合另一个线程.但问题是,python肯定是在等式的鸭子打字方面,如果你打算用Python做很多编程,你可能不得不习惯这样的语法(但这并不意味着你必须喜欢它当然).

您可能需要考虑的另一件事是:与许多其他语言相比,Python在抛出和捕获异常方面相当快(例如,比.Net快30倍).哎呀,语言本身甚至会抛出异常来传达非常规的正常程序条件(每次使用for循环).因此,在您发现重大问题之前,我不会过多担心此代码的性能方面.


Sdw*_*daw 23

用于int此:

>>> "1221323".isdigit()
True
Run Code Online (Sandbox Code Playgroud)

但是因为float我们需要一些技巧;-).每个浮点数都有一点......

>>> "12.34".isdigit()
False
>>> "12.34".replace('.','',1).isdigit()
True
>>> "12.3.4".replace('.','',1).isdigit()
False
Run Code Online (Sandbox Code Playgroud)

对于负数,只需添加lstrip():

>>> '-12'.lstrip('-')
'12'
Run Code Online (Sandbox Code Playgroud)

现在我们得到一个通用的方式:

>>> '-12.34'.lstrip('-').replace('.','',1).isdigit()
True
>>> '.-234'.lstrip('-').replace('.','',1).isdigit()
False
Run Code Online (Sandbox Code Playgroud)

  • 不处理像`1.234e56`之类的东西.另外,我很感兴趣你怎么知道`99999999999999999999e99999999999999999999`不是数字.试图解析它很快发现. (2认同)

Eva*_*ice 15

只是模仿C#

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

  • Float.Parse()
  • Float.TryParse()

float.parse():

def parse(string):
    try:
        return float(string)
    except Exception:
        throw TypeError
Run Code Online (Sandbox Code Playgroud)

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

float.try_parse():

def try_parse(string, fail=None):
    try:
        return float(string)
    except Exception:
        return fail;
Run Code Online (Sandbox Code Playgroud)

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

要扩展float以包含'parse()'和'try_parse()',您需要monkeypatch'float'类来添加这些方法.

如果您想要尊重预先存在的函数,代码应该是这样的:

def monkey_patch():
    if(!hasattr(float, 'parse')):
        float.parse = parse
    if(!hasattr(float, 'try_parse')):
        float.try_parse = try_parse
Run Code Online (Sandbox Code Playgroud)

SideNote:我个人更喜欢称之为Monkey Punching,因为当我这样做时,感觉就像是在滥用语言而是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
Run Code Online (Sandbox Code Playgroud)

伟大的Sage Pythonas向教廷Sharpisus说:"你能做的任何事情我都可以做得更好;我能做比你更好的事情."


Set*_*ton 15

对于非数字字符串,try: 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()
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)

如你看到的

  • try: except: 数字输入速度很快,但输入无效则很慢
  • 当输入无效时,正则表达式非常有效
  • fastnumbers 两种情况都胜出

  • 针对此线程中的最佳替代方案进行了测试,我确认此解决方案是 ** 迄今为止** 最快的。第二快的方法是 `str(s).strip('-').replace('.','',1).isdigit()` 大约慢 10 倍! (2认同)

Aru*_*olf 14

我知道这个特别古老,但我会添加一个答案,我认为这些答案涵盖了最高投票答案中缺少的信息,对于任何发现这一点的人来说都是非常有价值的:

对于以下每种方法,如果需要接受任何输入,请将它们与计数相连.(假设我们使用整数的声音定义而不是0-255等)

x.isdigit() 适用于检查x是否为整数.

x.replace('-','').isdigit() 适用于检查x是否为负数.(签到第一个位置)

x.replace('.','').isdigit() 适用于检查x是否为小数.

x.replace(':','').isdigit() 适用于检查x是否为比率.

x.replace('/','',1).isdigit() 适用于检查x是否为分数.

  • 尽管对于分数,您可能需要执行 `x.replace('/','',1).isdigit()` ,否则诸如 4/7/2017 之类的日期将被误解为数字。 (3认同)

cod*_*gic 11

转换为float并捕获ValueError可能是最快的方法,因为float()专门用于此.任何需要字符串解析(正则表达式等)的东西都可能会因为没有针对此操作进行调整而变慢.我的0.02美元.

  • 你的"2e-2"美元也是一个浮动(使用浮动的另一个参数:) (10认同)
  • @tzot永远不要使用浮点数来表示货币价值. (7认同)
  • @Luke:我完全同意你的观点,尽管我从未建议使用花车代表货币价值; 我只是说货币价值*可以*表示为浮点数:) (5认同)

Bla*_*iro 11

你可以使用Unicode字符串,他们有一个方法可以做你想要的:

>>> s = u"345"
>>> s.isnumeric()
True
Run Code Online (Sandbox Code Playgroud)

要么:

>>> s = "345"
>>> u = unicode(s)
>>> u.isnumeric()
True
Run Code Online (Sandbox Code Playgroud)

http://www.tutorialspoint.com/python/string_isnumeric.htm

http://docs.python.org/2/howto/unicode.html

  • 啊!!!! 算了,它只检查所有字符是否都是数字.抱歉. (3认同)
  • 对于非负整数,没关系;-) (2认同)

Moi*_*dri 11

这个答案提供了一步一步的指南,其中有一些函数用例来查找字符串:

  • 正整数
  • 正/负 - 整数/浮点数
  • 如何在检查号码时丢弃"NaN"(不是数字)字符串?

检查字符串是否为整数

您可以使用str.isdigit()检查给定字符串是否为整数.

样本结果:

# For digit
>>> '1'.isdigit()
True
>>> '1'.isalpha()
False
Run Code Online (Sandbox Code Playgroud)

检查字符串为正/负 - 整数/浮点数

str.isdigit()False如果字符串是负数或浮点数,则返回.例如:

# returns `False` for float
>>> '123.3'.isdigit()
False
# returns `False` for negative number
>>> '-123'.isdigit()
False
Run Code Online (Sandbox Code Playgroud)

如果你还想检查整数float,那么你可以编写一个自定义函数来检查它:

def is_number(n):
    try:
        float(n)   # Type-casting the string to `float`.
                   # If string is not a valid `float`, 
                   # it'll raise `ValueError` exception
    except ValueError:
        return False
    return True
Run Code Online (Sandbox Code Playgroud)

样品运行:

>>> is_number('123')    # positive integer number
True

>>> is_number('123.4')  # positive float number
True

>>> is_number('-123')   # negative integer number
True

>>> is_number('-123.4') # negative `float` number
True

>>> is_number('abc')    # `False` for "some random" string
False
Run Code Online (Sandbox Code Playgroud)

检查号码时丢弃"NaN"(不是数字)字符串

上面的函数将返回True"NAN"(非数字)字符串,因为对于Python,它是有效的float,表示它不是数字.例如:

>>> is_number('NaN')
True
Run Code Online (Sandbox Code Playgroud)

为了检查数字是否为"NaN",您可以使用math.isnan():

>>> import math
>>> nan_num = float('nan')

>>> math.isnan(nan_num)
True
Run Code Online (Sandbox Code Playgroud)

或者,如果您不想导入其他库来检查这一点,那么您可以通过比较它自己来检查它==.Falsenanfloat与自身进行比较时,Python会返回.例如:

# `nan_num` variable is taken from above example
>>> nan_num == nan_num
False
Run Code Online (Sandbox Code Playgroud)

因此,上述功能is_number可以更新,返回False"NaN"是:

def is_number(n):
    is_number = True
    try:
        num = float(n)
        # check for "nan" floats
        is_number = num == num   # or use `math.isnan(num)`
    except ValueError:
        is_number = False
    return is_number
Run Code Online (Sandbox Code Playgroud)

样品运行:

>>> is_number('Nan')   # not a number "Nan" string
False

>>> is_number('nan')   # not a number string "nan" with all lower cased
False

>>> is_number('123')   # positive integer
True

>>> is_number('-123')  # negative integer
True

>>> is_number('-1.12') # negative `float`
True

>>> is_number('abc')   # "some random" string
False
Run Code Online (Sandbox Code Playgroud)

PS:每个检查的每个操作取决于数字的类型带来额外的开销.选择is_number适合您要求的功能版本.


Sid*_*thy 10

在最常见的浮点数情况下,我们需要处理整数和小数。让我们取字符串"1.1"为例。

\n

我会尝试以下其中一项:

\n

1.> 是数字()

\n
word = "1.1"\n\n"".join(word.split(".")).isnumeric()\n>>> True\n
Run Code Online (Sandbox Code Playgroud)\n

2.> 是数字()

\n
word = "1.1"\n\n"".join(word.split(".")).isdigit()\n>>> True\n
Run Code Online (Sandbox Code Playgroud)\n

3.> isdecimal()

\n
word = "1.1"\n\n"".join(word.split(".")).isdecimal()\n>>> True\n
Run Code Online (Sandbox Code Playgroud)\n

速度:

\n

\xe2\x96\xba 所有上述方法都有相似的速度。

\n
%timeit "".join(word.split(".")).isnumeric()\n>>> 257 ns \xc2\xb1 12 ns per loop (mean \xc2\xb1 std. dev. of 7 runs, 1000000 loops each)\n\n%timeit "".join(word.split(".")).isdigit()\n>>> 252 ns \xc2\xb1 11 ns per loop (mean \xc2\xb1 std. dev. of 7 runs, 1000000 loops each)\n\n%timeit "".join(word.split(".")).isdecimal()\n>>> 244 ns \xc2\xb1 7.17 ns per loop (mean \xc2\xb1 std. dev. of 7 runs, 1000000 loops each)\n
Run Code Online (Sandbox Code Playgroud)\n


Ron*_*ter 9

我想看看哪种方法最快.总体而言,该check_replace功能给出了最佳和最一致的结果.最快的结果是由check_exception函数给出的,但是只有在没有异常被触发的情况下 - 意味着它的代码是最有效的,但抛出异常的开销非常大.

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

huge_number = float('1e+100')
Run Code Online (Sandbox Code Playgroud)

这是基准代码:

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))
Run Code Online (Sandbox Code Playgroud)

以下是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
Run Code Online (Sandbox Code Playgroud)

以下是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
Run Code Online (Sandbox Code Playgroud)

以下是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
Run Code Online (Sandbox Code Playgroud)

  • 您还应该测试无效案例的性能.这些数字没有异常,这正是"慢"部分. (10认同)

a1a*_*1an 7

所以把它们放在一起,检查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
Run Code Online (Sandbox Code Playgroud)


Dav*_*lar 7

我认为你的解决方案很好,但是有一个正确的正则表达式实现。

似乎确实有很多正则表达式讨厌这些答案,我认为这是不合理的,正则表达式可以相当干净、正确和快速。这实际上取决于您想要做什么。最初的问题是如何“检查字符串是否可以表示为数字(浮点数)”(根据您的标题)。假设您在检查数字/浮点值是否有效后会想要使用它,在这种情况下,您的 try/ except 很有意义。但是,如果出于某种原因,您只想验证字符串是否是数字,那么正则表达式也可以正常工作,但很难得到正确的结果。例如,我认为到目前为止,大多数正则表达式答案都无法正确解析没有整数部分(例如“.7”)的字符串,就Python而言,整数部分是浮点数。在不需要小数部分的单个正则表达式中检查这有点棘手。我包含了两个正则表达式来展示这一点。

它确实提出了一个有趣的问题:“数字”是什么。您是否包含在 python 中作为浮点数有效的“inf”?或者您是否包含“数字”但可能无法在 python 中表示的数字(例如大于 float max 的数字)。

解析数字的方式也存在歧义。例如,“--20”怎么样?这是一个“数字”吗?这是表示“20”的合法方式吗?Python 会让你执行“var = --20”并将其设置为 20(尽管实际上这是因为它将其视为表达式),但 float("--20") 不起作用。

无论如何,没有更多信息,这里有一个正则表达式,我相信它涵盖了python 解析它们时的所有整数和浮点数。

# Doesn't properly handle floats missing the integer part, such as ".7"
SIMPLE_FLOAT_REGEXP = re.compile(r'^[-+]?[0-9]+\.?[0-9]+([eE][-+]?[0-9]+)?$')
# Example "-12.34E+56"      # sign (-)
                            #     integer (12)
                            #           mantissa (34)
                            #                    exponent (E+56)

# Should handle all floats
FLOAT_REGEXP = re.compile(r'^[-+]?([0-9]+|[0-9]*\.[0-9]+)([eE][-+]?[0-9]+)?$')
# Example "-12.34E+56"      # sign (-)
                            #     integer (12)
                            #           OR
                            #             int/mantissa (12.34)
                            #                            exponent (E+56)

def is_float(str):
  return True if FLOAT_REGEXP.match(str) else False
Run Code Online (Sandbox Code Playgroud)

一些测试值示例:

True  <- +42
True  <- +42.42
False <- +42.42.22
True  <- +42.42e22
True  <- +42.42E-22
False <- +42.42e-22.8
True  <- .42
False <- 42nope
Run Code Online (Sandbox Code Playgroud)

运行 @ron-reiter 的答案中的基准测试代码表明,该正则表达式实际上比正常的正则表达式更快,并且处理坏值的速度比异常快得多,这是有道理的。结果:

check_regexp with good floats: 18.001921
check_regexp with bad floats: 17.861423
check_regexp with strings: 17.558862
check_correct_regexp with good floats: 11.04428
check_correct_regexp with bad floats: 8.71211
check_correct_regexp with strings: 8.144161
check_replace with good floats: 6.020597
check_replace with bad floats: 5.343049
check_replace with strings: 5.091642
check_exception with good floats: 5.201605
check_exception with bad floats: 23.921864
check_exception with strings: 23.755481
Run Code Online (Sandbox Code Playgroud)


小智 6

输入可能如下:

a="50" b=50 c=50.1 d="50.1"


1-常规输入:

此功能的输入可以是所有内容!

查找给定变量是否为数字。数字字符串包括可选符号,任意数量的数字,可选小数部分和可选指数部分。因此,+ 0123.45e6是有效的数值。不允许使用十六进制(例如0xf4c3b00c)和二进制(例如0b10100111001)表示法。

is_numeric函数

import ast
import numbers              
def is_numeric(obj):
    if isinstance(obj, numbers.Number):
        return True
    elif isinstance(obj, str):
        nodes = list(ast.walk(ast.parse(obj)))[1:]
        if not isinstance(nodes[0], ast.Expr):
            return False
        if not isinstance(nodes[-1], ast.Num):
            return False
        nodes = nodes[1:-1]
        for i in range(len(nodes)):
            #if used + or - in digit :
            if i % 2 == 0:
                if not isinstance(nodes[i], ast.UnaryOp):
                    return False
            else:
                if not isinstance(nodes[i], (ast.USub, ast.UAdd)):
                    return False
        return True
    else:
        return False
Run Code Online (Sandbox Code Playgroud)

测试:

>>> is_numeric("54")
True
>>> is_numeric("54.545")
True
>>> is_numeric("0x45")
True
Run Code Online (Sandbox Code Playgroud)

is_float函数

查找给定变量是否为float。浮点字符串包含可选符号,任意数量的数字,...

import ast

def is_float(obj):
    if isinstance(obj, float):
        return True
    if isinstance(obj, int):
        return False
    elif isinstance(obj, str):
        nodes = list(ast.walk(ast.parse(obj)))[1:]
        if not isinstance(nodes[0], ast.Expr):
            return False
        if not isinstance(nodes[-1], ast.Num):
            return False
        if not isinstance(nodes[-1].n, float):
            return False
        nodes = nodes[1:-1]
        for i in range(len(nodes)):
            if i % 2 == 0:
                if not isinstance(nodes[i], ast.UnaryOp):
                    return False
            else:
                if not isinstance(nodes[i], (ast.USub, ast.UAdd)):
                    return False
        return True
    else:
        return False
Run Code Online (Sandbox Code Playgroud)

测试:

>>> is_float("5.4")
True
>>> is_float("5")
False
>>> is_float(5)
False
>>> is_float("5")
False
>>> is_float("+5.4")
True
Run Code Online (Sandbox Code Playgroud)

什么是ast


2-如果您确信变量内容为String

使用str.isdigit()方法

>>> a=454
>>> a.isdigit()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'int' object has no attribute 'isdigit'
>>> a="454"
>>> a.isdigit()
True
Run Code Online (Sandbox Code Playgroud)

3个数字输入:

检测int值:

>>> isinstance("54", int)
False
>>> isinstance(54, int)
True
>>> 
Run Code Online (Sandbox Code Playgroud)

检测浮动:

>>> isinstance("45.1", float)
False
>>> isinstance(45.1, float)
True
Run Code Online (Sandbox Code Playgroud)


zar*_*sht 6

str.isnumeric()

返回True如果字符串中的所有字符都是数字字符,并且至少有一个字符,False否则。数字字符包括数字字符,以及所有具有Unicode 数值属性的字符,例如U+2155、庸俗分数五分之一。形式上,数字字符是具有属性值 Numeric_Type=Digit、Numeric_Type=Decimal 或 Numeric_Type=Numeric 的字符。

str.isdecimal()

返回True如果字符串中的所有字符都是十进制字符,至少有一个字符,False否则。十进制字符是那些可用于形成以 10 为基数的数字的字符,例如 U+0660、ARABIC-INDIC DIGIT ZERO。正式的十进制字符是 Unicode 通用类别“Nd”中的字符。

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


小智 5

我需要确定字符串是否转换为基本类型(float、int、str、bool)。在互联网上找不到任何内容后,我创建了这个:

def str_to_type (s):
    """ Get possible cast type for a string

    Parameters
    ----------
    s : string

    Returns
    -------
    float,int,str,bool : type
        Depending on what it can be cast to

    """    
    try:                
        f = float(s)        
        if "." not in s:
            return int
        return float
    except ValueError:
        value = s.upper()
        if value == "TRUE" or value == "FALSE":
            return bool
        return type(s)
Run Code Online (Sandbox Code Playgroud)

例子

str_to_type("true") # bool
str_to_type("6.0") # float
str_to_type("6") # int
str_to_type("6abc") # str
str_to_type(u"6abc") # unicode       
Run Code Online (Sandbox Code Playgroud)

您可以捕获类型并使用它

s = "6.0"
type_ = str_to_type(s) # float
f = type_(s) 
Run Code Online (Sandbox Code Playgroud)