如何检查字符串是否代表数字(float 或 int)?

How do I check if a string represents a number (float or int)?

提问人:Daniel Goldberg 提问时间:12/10/2008 最后编辑:Karl KnechtelDaniel Goldberg 更新时间:7/12/2023 访问量:1712749

问:

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

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

以上有效,但看起来很笨拙。


如果要测试的内容来自用户输入,则它仍然是一个字符串,即使它表示 intfloat。请参阅如何以数字形式读取输入?以转换输入,以及要求用户输入,直到他们给出有效响应,以确保输入表示 intfloat(或其他要求),然后再继续。

Python 浮点 类型转换

评论

99赞 Colonel Panic 3/22/2013
您当前的解决方案有什么问题?它简短、快速且可读性强。
5赞 Thruston 5/25/2013
而且您不必只返回 True 或 False。您可以返回经过适当修改的值 - 例如,您可以使用它来将非数字放在引号中。
8赞 Jiminion 7/25/2013
在成功转换的情况下,返回浮点数的结果不是更好吗?您仍然需要检查成功(结果为 False),并且您实际上拥有转换,无论如何您都可能想要转换。
10赞 thiruvenkadam 10/7/2013
尽管这个问题更古老,但我只想说这是一种优雅的方式,被记录为 EAFP。所以可能是解决这类问题的最佳方法。
9赞 ovangle 1/5/2016
失败时不返回 float(s) 或 None 的结果。如果你随后使用它,因为你现在的代码中有一个错误。真实值是这些函数引发异常而不是首先返回的原因。更好的解决方案是避免使用实用程序函数,并在要使用它时将 float 的调用包围起来。x = float('0.00'); if x: use_float(x);Nonetry catch

答:

1772赞 Zoomulator 12/10/2008 #1

仅对于非负(无符号)整数,请使用 isdigit()

>>> a = "03523"
>>> a.isdigit()
True
>>> b = "963spam"
>>> b.isdigit()
False

适用的文档:Python2Python3isdigit()

对于 Python 2 Unicode 字符串:isnumeric()。

评论

254赞 intrepion 10/23/2009
这也是负面的负面因素
34赞 ssc 5/12/2011
指数也失败: '1e3'.isdigit() --> False
39赞 Adam Parkin 8/22/2012
虽然 Number != Digit,但正在寻找测试字符串是否包含整数的方法的人很可能会偶然发现这个问题,而 isDigit 方法可能非常适合他们的应用程序。
14赞 jfs 11/17/2012
@AdamParkin:并且对什么是整数有不同的意见,例如,对于Unicode字符u'\u00b9':是但会引发ValueError。isdigit()int()u'¹'.isdigit()Trueint(u'¹')
9赞 Justin Johnson 6/19/2013
+1:isdigit() 可能不是 OP 想要的,但这正是我想要的。这个答案和方法可能并不涵盖所有类型的数字,但它仍然具有高度相关性,这与关于其准确性的争论相反。虽然“数字 != 数字”,但数字仍然是数字的子集,尤其是正数、非负数并使用以 1-10 为基数的数字。此外,对于要检查字符串是否为数字 ID 的情况,此方法特别有用且简短,这通常属于我刚才描述的数字子集。
778赞 S.Lott 12/10/2008 #2

其中,不仅丑陋而缓慢

我会对两者都提出异议。

正则表达式或其他字符串解析方法会更丑陋、更慢。

我不确定有什么能比上面更快。它调用函数并返回。Try/Catch 不会带来太多开销,因为最常见的异常是在未对堆栈帧进行广泛搜索的情况下捕获的。

问题在于,任何数值转换函数都有两种结果

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

C(举个例子)通过多种方式解决这个问题。Python 清晰明确地阐述了它。

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

评论

31赞 Eric O. Lebigot 7/5/2013
我不认为代码是完美的(但我认为它非常接近):更常见的是将“测试”的部分放在子句中,所以我会把 放在子句的子句中。原因之一是,对于问题中的代码,如果我必须检查它,我必须检查子句中的第二个语句是否不能引发 ValueError:当然,这不需要太多的时间或脑力,但是为什么在不需要的时候使用 any?tryreturn Trueelsetrytry
5赞 sage 12/29/2013
答案似乎很有说服力,但让我想知道为什么它不是开箱即用的......我会复制它并在任何情况下使用它。
17赞 Basic 3/10/2014
多么可怕。如果我不在乎这个数字是什么,只是它是一个数字(这就是把我带到这里的原因)怎么样?而不是 1 行,我要么以 try/catch 结束,要么以另一个包装 try/catch 结束。呸IsNumeric()
6赞 ovangle 1/5/2016
它不是“开箱即用”提供的,因为其代码行数与 .这个效用函数是一个完全不必要的抽象。if is_number(s): x = float(x) else: // failtry: x = float(x) catch TypeError: # fail
21赞 JamEngulfer 3/18/2016
但抽象是库的全部意义所在。拥有“isNumber”函数(在任何语言中)都有很大帮助,因为您可以将其直接构建到 if 语句中,并且具有依赖于 try - catch 块的更具可读性和可维护性的代码。此外,如果您需要在多个类/模块中多次使用代码,那么您使用的代码行数将超过内置函数的行数。
12赞 codelogic 12/10/2008 #3

转换为浮点并捕获 ValueError 可能是最快的方法,因为 float() 专门用于此。需要字符串解析(正则表达式等)的任何其他内容都可能较慢,因为它没有针对此操作进行优化。我的 0.02 美元。

评论

12赞 tzot 12/10/2008
您的“2e-2”美元也是一个浮点数(使用浮点数的附加参数:)
9赞 Luke 11/7/2012
@tzot永远不要使用浮点数来表示货币价值。
6赞 tzot 11/8/2012
@Luke:我完全同意你的看法,尽管我从未建议使用浮点数来表示货币价值;我刚才说过,货币价值可以表示为浮点数:)
45赞 Jason Baker 12/11/2008 #4

这不仅丑陋而缓慢,而且看起来很笨拙。

这可能需要一些时间来适应,但这是 pythonic 的方式。正如已经指出的那样,替代方案更糟。但这样做还有一个好处:多态性。

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

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

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

评论

1赞 kindall 6/11/2011
Python 对基本函数使用异常的另一个常见地方是,其中只是一个包装在 .尽管如此,异常处理比正常的流控制要慢,因此将其用于大多数情况下都是正确的事情可能会导致性能下降。hasattr()getattr()try/except
0赞 Basic 3/10/2014
看来,如果你想要一句话,你就是 SOL
0赞 heltonbiker 4/26/2016
同样是pythonic的想法,即“请求宽恕比请求许可更好”,关于廉价例外的影响。
1赞 Anil 7/17/2009 #5

这是我的简单方法。假设我正在遍历一些字符串,如果它们变成数字,我想将它们添加到数组中。

try:
    myvar.append( float(string_to_check) )
except:
    continue

如果字符串是数字,请将 myvar.apppend 替换为要对字符串执行的任何操作。这个想法是尝试使用 float() 操作并使用返回的错误来确定字符串是否为数字。

评论

0赞 DarwinSurvivor 7/24/2013
您应该将该函数的追加部分移动到 else 语句中,以避免在数组出现问题时意外触发异常。
49赞 3 revsMatthew Wilcoxson #6

在 Alfe 指出您不需要单独检查浮点数后更新,因为复杂处理两者:

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

    return True

前面说过:在极少数情况下,您可能还需要检查复数(例如 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

评论

15赞 Jiminion 7/25/2013
我不同意。这在正常使用中是不太可能的,你最好在使用它们时构建一个 is_complex_number() 调用,而不是用额外的操作来增加调用的负担,因为误操作的可能性为 0.0001%。
3赞 Alfe 4/22/2016
您可以完全剥离这些东西,然后检查调用是否成功。解析的所有内容都可以解析。float()complex()float()complex()
0赞 fixxxer 5/29/2016
此函数将返回 Pandas 的 NaN 和 Inf 值作为数值。
1赞 plhn 12/20/2018
complex('(01989)')将返回.但会失败。所以我认为使用不是一个好主意。(1989+0j)float('(01989)')complex
0赞 Cecil Curry 9/25/2020
哎呀。奇怪的是,它接受了 - 和 - 分隔的语法 - 大概是为了解释复数背后的虚平面中的复合向量加法,但仍然如此。正如@plhn所建议的,使用 here 会招致误报。不要在生产代码中执行此操作。老实说,对于大多数用例来说,它仍然是最佳解决方案。complex()()complex()s.lstrip('-').replace('.','',1).replace('e-','',1).replace('e','',1).isdigit()
83赞 W7GVR 9/1/2010 #7

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

如果你想is_number 'NaN' 返回 FALSE,这段代码将不起作用,因为 Python 会将其转换为非数字的数字表示形式(讨论身份问题):

>>> float('NaN')
nan

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

G.

评论

4赞 kindall 6/11/2011
实际上,如果传递的文本实际上不是数字的表示形式,则返回(而不是)可能是一个很好的值。检查它是一种痛苦(Python 的类型确实需要一种方法),但您可以在计算中使用它而不会产生错误,并且只需要检查结果。NaNFalsefloat
11赞 agf 5/23/2012
另一个例外是字符串 。either or 也可以以 or 为前缀,并且仍被接受。'inf'infNaN+-
4赞 RyanN 3/16/2013
如果要为 NaN 和 Inf 返回 False,请将行更改为 x = float(s);return (x == x) 和 (x - 1 != x)。对于除 Inf 和 NaN 之外的所有浮点数,这都应返回 True
6赞 Steve Jessop 1/23/2014
x-1 == x对于小于 的大型浮点数为 true。从 Python 3.2 开始,您可以使用它来测试既不是 NaN 也不是无限大的数字,或者在此之前检查两者。infmath.isfinitemath.isnanmath.isinf
4赞 FxIII 10/12/2010 #8

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

14赞 Evan Plaice 2/18/2012 #9

只是模仿C#

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

  • 浮点.解析()
  • 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' 类进行猴子修补以添加这些方法。

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

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

旁注:我个人更喜欢称它为 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

伟大的蝒蛇对教廷夏皮苏斯说:“你能做的任何事情,我都能做得更好;我可以做得比你更好。

评论

0赞 Evan Plaice 2/18/2012
我最近主要用 JS 编码,并没有真正测试过这一点,所以可能会有一些小错误。如果您看到任何错误,请随时纠正我的错误。
0赞 Evan Plaice 2/18/2012
要添加对复数的支持,请参阅 @Matthew Wilcoxson 的答案。stackoverflow.com/a/3335060/290340
1赞 BlackJack 8/28/2016
使用 instead of 可能是一个小错误,但您绝对不能将属性分配给 CPython 中的内置。!notfloat
0赞 Janus Troelsen 9/8/2020
因不分青红皂白地捕获所有异常以及使用不存在的关键字“throw”而投了反对票
0赞 nurettin 11/8/2021
我是标记“不回答问题”的人。
9赞 a1an 3/24/2012 #10

因此,将所有这些放在一起,检查 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

评论

0赞 anish 1/15/2020
到目前为止最好的答案。谢谢
67赞 haxwithaxe 5/26/2012 #11

这个怎么样:

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

仅当数字字符串中有一个或没有“.”时,才会返回 true。

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

将返回 false

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

评论

8赞 Michael Barton 10/24/2014
然而,这并不考虑负数。
6赞 Alfe 4/22/2016
或带有指数的数字,例如(也可以写成和更多变体)。1.234e56+1.234E+56
0赞 Baldrickk 2/9/2017
re.match(r'^[+-]*(0[xbo])?[0-9A-Fa-f]*\.?[0-9A-Fa-f]*(E[+-]*[0-9A-Fa-f]+)$', 'str')应该更好地确定一个数字(但不是全部,我不是这么说)。我不建议使用它,最好使用提问者的原始代码。
0赞 aloisdg 2/23/2018
如果您不喜欢此解决方案,请在投反对票之前阅读内容!
0赞 Karam Qusai 12/6/2019
伙计,这是我在这个网站上见过的最聪明的解决方案!,干得好!
10赞 Ron Reiter 1/16/2013 #12

我想看看哪种方法最快。总体而言,该函数给出了最佳和最一致的结果。该函数给出了最快的结果,但前提是没有触发异常 - 这意味着它的代码是最有效的,但抛出异常的开销相当大。check_replacecheck_exception

请注意,检查是否成功强制转换是唯一准确的方法,例如,这适用于 但其他两个测试函数将返回 False 以获取有效的浮点数:check_exception

huge_number = float('1e+100')

以下是基准测试代码:

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))

以下是 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

以下是 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

以下是 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

评论

0赞 David Ljung Madison Stellar 1/29/2020
“请注意,检查是否成功铸造是唯一准确的方法”<——这实际上并非如此。我在上面的答案中使用正则表达式运行了您的测试,它实际上比正则表达式运行得更快。我会将结果添加到上面的答案中。
0赞 David Ljung Madison Stellar 1/29/2020
顺便说一句,有趣的是,你的坏数字创建者实际上可以创建一些合法的数字,尽管这是非常罕见的。:)
12赞 Blackzafiro 3/5/2013 #13

您可以使用Unicode字符串,它们有一种方法可以执行您想要的操作:

>>> s = u"345"
>>> s.isnumeric()
True

艺术

>>> s = "345"
>>> u = unicode(s)
>>> u.isnumeric()
True

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

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

评论

2赞 andilabs 3/22/2014
对于非负整数,这是可以的;-)
1赞 jfs 10/19/2014
s.isdecimal()检查字符串是否为非负整数。 包括拒绝的字符。ss.isnumeric()int()
0赞 Thruston 5/25/2013 #14

通过返回比 True 和 False 更有用的值,可以以有用的方式概括异常技术。例如,此函数将引号放在圆角字符串中,但不保留数字。这正是我所需要的快速而肮脏的过滤器,以便为 R 进行一些变量定义。

import sys

def fix_quotes(s):
    try:
        float(s)
        return s
    except ValueError:
        return '"{0}"'.format(s)

for line in sys.stdin:
    input = line.split()
    print input[0], '<- c(', ','.join(fix_quotes(c) for c in input[1:]), ')'
3赞 philh 7/29/2013 #15

RyanN 建议

如果要为 NaN 和 Inf 返回 False,请将行更改为 x = float(s);return (x == x) 和 (x - 1 != x)。对于除 Inf 和 NaN 之外的所有浮点数,这都应返回 True

但这并不完全有效,因为对于足够大的浮点数,返回 true。例如x-1 == x2.0**54 - 1 == 2.0**54

319赞 user2489252 5/14/2014 #16

TL;DR:最好的解决方案是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()

如果字符串不是数字,则 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__)

浮点数表示法“.1234”不受以下支持:

  • is_number_regex

    科学1 = '1.000000e+50' 科学2 = '1e50'

    print('科学记数法 “1.000000e+50” 不支持:') 对于 Fin Funcs : 如果不是 f(科学1): print('\t -', f.name)

    print('科学记数法 “1e50” 不支持:') 对于 Fin Funcs : 如果不是 f(scientific2): print('\t -', f.name)

科学记数法“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()

enter image description here

评论

32赞 jcchuks 11/19/2016
对于漂亮的图表 +1。我看到了基准和图表,所有的TL;DR的事情变得清晰直观。
15赞 Urchin 4/10/2019
此方法不处理负数(短划线)。我主张只使用 float 方法,因为它不容易出错并且每次都能奏效。
8赞 Markus von Broady 4/24/2019
需要注意的重要一点是,即使假设不能有破折号,replace-isdigit 方法也只对非数字(False 结果)更快,而 try-except 方法对数字(True 结果)更快。如果您的大部分输入都是有效的输入,则最好使用“除尝试”解决方案!
4赞 EL_DON 10/18/2019
不适用于指数表示法,例如负数。'1.5e-9'
7赞 Cecil Curry 9/25/2020
太棒了,除了幂和负数的假阴性的明显警告之外——你可以通过链接调用来简单地纠正这些错误。例如,处理幂。然后要处理负数,只需将第一个字符(如果是破折号)左去。例如。是的,我已经详尽地测试了该单行代码,并且可以确认它的行为符合预期。s.replace()s.replace('.','',1).replace('e-','',1).replace('e','',1).isdigit()s.lstrip('-').replace('.','',1).replace('e-','',1).replace('e','',1).isdigit()
5赞 astrodsg 7/4/2014 #17

我需要确定字符串是否转换为基本类型(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)

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       

您可以捕获类型并使用它

s = "6.0"
type_ = str_to_type(s) # float
f = type_(s) 

评论

0赞 joanis 11/9/2021
很好的答案,但并不完全通用:返回时返回。此外,返回 .str_to_type("123e-4")intfloat("123e-4")0.0123str_to_type("NaN")int
0赞 joanis 11/9/2021
更改为修复我在此处显示的情况,但它使代码更笨拙,我不确定它是否会捕获所有情况。if "." not in s:if "." not in s and "e" not in s and "N" not in s:
0赞 joanis 11/9/2021
我首选的解决方案,也是更安全的解决方案,是使用嵌套的 try/except 语句:包装到第一个 try/except 中,然后放入第二个 try/except 中,第一个 try/except 的所有 except 块。类似于 user1508746 答案的结构,具有不同的返回值。i = int(s); return intf = float(s); return float
18赞 SethMMorton 8/14/2014 #18

对于非数字字符串,实际上比正则表达式慢。对于有效数字的字符串,正则表达式速度较慢。因此,适当的方法取决于您的输入。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()

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在这两种情况下都获胜

评论

0赞 Alfe 4/23/2016
我纠正了:-}它看起来不像是在这样做。也许使用像 和 这样的名字可以防止我的错误。prep_code_basisprep_code_re_method
0赞 Solomon Ucko 5/5/2016
你介意解释一下你的模块是如何工作的,至少对于这个功能来说是这样吗?isfloat
0赞 SethMMorton 5/5/2016
@SolomonUcko 以下是字符串检查部分的源代码链接:github.com/SethMMorton/fastnumbers/blob/v1.0.0/src/...。基本上,它按顺序遍历字符串中的每个字符,并验证它是否遵循有效浮点数的模式。如果输入已经是数字,则只使用快速PyFloat_Check
3赞 Alexander McFarlane 8/22/2018
针对此线程中的最佳替代方案进行了测试,我确认该解决方案是迄今为止最快的。第二快的方法是大约慢 10 倍!str(s).strip('-').replace('.','',1).isdigit()
0赞 mic 10/13/2020
请注意,该语句将运行 100 万次。我很困惑为什么这些数字看起来这么慢。timeit.timeit
3赞 user1508746 11/9/2014 #19

我正在研究一个问题,这个问题导致我进入这个线程,即如何以最直观的方式将数据集合转换为字符串和数字。在阅读原始代码后,我意识到我需要的东西在两个方面有所不同:

1 - 如果字符串表示整数,我想要一个整数结果

2 - 我希望将数字或字符串结果粘贴到数据结构中

所以我改编了原始代码来生成这个衍生品:

def string_or_number(s):
    try:
        z = int(s)
        return z
    except ValueError:
        try:
            z = float(s)
            return z
        except ValueError:
            return s
0赞 TheRedstoneLemon 5/31/2015 #20

试试这个。

 def is_number(var):
    try:
       if var == int(var):
            return True
    except Exception:
        return False

评论

0赞 geotheory 8/19/2015
无法响应is_number('10')
0赞 Solomon Ucko 5/5/2016
@geotheory,你说的“没有回应”是什么意思?
34赞 Sdwdaw 9/8/2015 #21

为此,请执行以下操作:int

>>> "1221323".isdigit()
True

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

>>> "12.34".isdigit()
False
>>> "12.34".replace('.','',1).isdigit()
True
>>> "12.3.4".replace('.','',1).isdigit()
False

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

>>> '-12'.lstrip('-')
'12'

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

>>> '-12.34'.lstrip('-').replace('.','',1).isdigit()
True
>>> '.-234'.lstrip('-').replace('.','',1).isdigit()
False

评论

3赞 Alfe 4/22/2016
不处理类似的事情。另外,我很想知道你如何发现这不是一个数字。尝试解析它很快就会发现。1.234e5699999999999999999999e99999999999999999999
0赞 Zev Averbach 2/21/2017
这在 50m 字符串列表中的运行速度比公认的解决方案快 ~30%,在 5k 字符串列表中快 150%。👏
0赞 brewmanz 10/18/2021
请注意,返回 true;也许不是预期的>>> '--1234'.lstrip('-').replace('.','',1).isdigit()
15赞 Aruthawolf 1/5/2016 #22

我知道这特别古老,但我想补充一个答案,我相信涵盖了票数最高的答案中缺少的信息,这对任何发现它的人来说都是非常有价值的:

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

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

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

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

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

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

评论

3赞 Ethan Chen 4/7/2017
虽然对于分数,您可能需要这样做,否则 2017 年 4 月 7 日等日期会被误解为数字。x.replace('/','',1).isdigit()
0赞 Daniel Braun 4/11/2018
有关链接条件的最佳方法:stackoverflow.com/q/3411771/5922329
0赞 Avi Drucker 12/18/2022
与 Ethan Chen 的评论类似,我们只想替换第一个小数/句点字符,否则 0.2.5 等版本号将被视为有效的浮点数。因此,与其说是 ,不如对非负数进行更精细的检查,例如 5-9(“5 到 9”)与 -59(实际负数 59)等范围。x.replace('.','',1).isdigit()x.replace('.','').isdigit()
1赞 mathfac 10/16/2016 #23

我也使用了你提到的函数,但很快我注意到字符串作为“Nan”、“Inf”及其变体被认为是数字。因此,我建议您改进函数的版本,该版本将在这些类型的输入上返回 false,并且不会使“1e3”变体失败:

def is_float(text):
    try:
        float(text)
        # check for nan/infinity etc.
        if text.isalpha():
            return False
        return True
    except ValueError:
        return False
-3赞 donald 2/24/2017 #24

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

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')
34赞 Moinuddin Quadri 2/11/2018 #25

这个答案提供了分步指南,其中有查找字符串的示例:

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

检查字符串是否为整数

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

示例结果:

# For digit
>>> '1'.isdigit()
True
>>> '1'.isalpha()
False

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

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

# returns `False` for float
>>> '123.3'.isdigit()
False
# returns `False` for negative number
>>> '-123'.isdigit()
False

如果你还想检查整数和浮点数,那么你可以编写一个自定义函数来检查它,如下所示:

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

示例运行:

>>> 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

在检查数字时丢弃“NaN”(不是数字)字符串

上述函数将返回“NAN”(不是数字)字符串,因为对于 Python,它是有效的浮点数,表示它不是数字。例如:True

>>> is_number('NaN')
True

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

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

>>> math.isnan(nan_num)
True

或者,如果您不想导入其他库来检查这一点,那么您可以简单地通过使用 将其与自身进行比较来检查它。当 float 与自身进行比较时,Python 返回。例如:==Falsenan

# `nan_num` variable is taken from above example
>>> nan_num == nan_num
False

因此,可以更新上述函数is_number,以将“NaN”False 返回为:

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

示例运行:

>>> 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

PS:根据数字类型,每次检查的每个操作都会带来额外的开销。选择适合您要求is_number函数版本。

评论

1赞 Karl Knechtel 2/5/2023
这应该放在最前面,因为它充分解决了询问“数字”的歧义,并为多种解释提供了相应的解决方案。
-2赞 Alex Pinto 3/18/2018 #26

我也有类似的问题。我不想定义 isNumber 函数,而是想将字符串列表转换为浮点数,在高级术语中,这将是:

[ float(s) for s in list if isFloat(s)]

给定的是,我们无法真正将浮点数与 isFloat 函数分开:这两个结果应该由同一个函数返回。 此外,如果浮点数失败,则整个过程将失败,而不仅仅是忽略有故障的元素。另外,“0”是一个有效的数字,应该包含在列表中。过滤掉坏元素时,一定不要排除 0。

因此,必须以某种方式将上述理解修改为:

  • 如果列表中的任何元素无法转换,请忽略它并且不要引发异常
  • 避免对每个元素多次调用浮点数(一个用于转换,另一个用于测试)
  • 如果转换后的值为 0,则它仍应存在于最终列表中

我提出了一个受 C# 的 Nullable 数值类型启发的解决方案。这些类型在内部由具有数值的结构表示,并添加一个布尔值,指示该值是否有效:

def tryParseFloat(s):
    try:
        return(float(s), True)
    except:
        return(None, False)

tupleList = [tryParseFloat(x) for x in list]
floats = [v for v,b in tupleList if b]
2赞 xin.chen 8/2/2018 #27
import re
def is_number(num):
    pattern = re.compile(r'^[-+]?[-0-9]\d*\.\d*|[-+]?\.?[0-9]\d*$')
    result = pattern.match(num)
    if result:
        return True
    else:
        return False


​>>>: is_number('1')
True

>>>: is_number('111')
True

>>>: is_number('11.1')
True

>>>: is_number('-11.1')
True

>>>: is_number('inf')
False

>>>: is_number('-inf')
False

评论

2赞 Mark Dickinson 8/2/2018
你不考虑代表一个数字吗?1e6
10赞 user10461621 10/6/2018 #28

输入可能如下:

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

测试:

>>> is_numeric("54")
True
>>> is_numeric("54.545")
True
>>> is_numeric("0x45")
True

is_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

测试:

>>> is_float("5.4")
True
>>> is_float("5")
False
>>> is_float(5)
False
>>> is_float("5")
False
>>> is_float("+5.4")
True

什么是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

3-数字输入:

检测 int 值:

>>> isinstance("54", int)
False
>>> isinstance(54, int)
True
>>> 

检测浮点数:

>>> isinstance("45.1", float)
False
>>> isinstance(45.1, float)
True

评论

0赞 10/7/2018
什么是“”?ast
0赞 1/8/2021
对类型的见解
0赞 Ramon 1/10/2021
这在 try/except 中包装方法的测试下失败,并且有效。is_numeric("String 1")
2赞 ravi tanwar 12/16/2018 #29

此代码使用正则表达式处理指数、浮点数和整数。

return True if str1.lstrip('-').replace('.','',1).isdigit() or float(str1) else False

评论

0赞 ZygD 10/27/2022
遇到字符串时出错
7赞 David Ljung Madison Stellar 5/11/2019 #30

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

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

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

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

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

# 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

一些示例测试值:

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

在 @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

评论

0赞 David Ljung Madison Stellar 5/11/2019
希望这是对的 - 很想听听任何反例。:)
1赞 Samantha Atkins 8/16/2019 #31

用户助手功能:

def if_ok(fn, string):
  try:
    return fn(string)
  except Exception as e:
    return None

然后

if_ok(int, my_str) or if_ok(float, my_str) or if_ok(complex, my_str)
is_number = lambda s: any([if_ok(fn, s) for fn in (int, float, complex)])

评论

0赞 not2qubit 4/13/2022
看起来很有趣,但请解释您的解决方案以及如何使用它,并提供一些输入和输出。
1赞 Amir Saniyan 4/3/2020 #32
def is_float(s):
    if s is None:
        return False

    if len(s) == 0:
        return False

    digits_count = 0
    dots_count = 0
    signs_count = 0

    for c in s:
        if '0' <= c <= '9':
            digits_count += 1
        elif c == '.':
            dots_count += 1
        elif c == '-' or c == '+':
            signs_count += 1
        else:
            return False

    if digits_count == 0:
        return False

    if dots_count > 1:
        return False

    if signs_count > 1:
        return False

    return True
7赞 zardosht 4/16/2020 #33

str.isnumeric()

如果字符串中的所有字符都是数字字符,则返回, 否则,至少有一个字符。数值的 字符包括数字字符,以及具有 Unicode 数值属性,例如 U+2155、VULGAR FRACTION ONE 第五。从形式上讲,数字字符是具有属性值的字符 Numeric_Type=数字,Numeric_Type=十进制或 Numeric_Type=数字。TrueFalse

str.isdecimal()

如果字符串中的所有字符都是十进制字符,则返回 否则,至少有一个字符。十进制字符 是那些可以用来形成以 10 为基数的数字,例如 U+0660, 阿拉伯语-印度语数字零。从形式上讲,十进制字符是一个字符 在Unicode通用类别“Nd”中。TrueFalse

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

10赞 Siddharth Satpathy 12/6/2020 #34

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

我会尝试以下方法之一:

1.> isnumeric()

word = "1.1"

"".join(word.split(".")).isnumeric()
>>> True

2.> isdigit()

word = "1.1"

"".join(word.split(".")).isdigit()
>>> True

3.> isdecimal()

word = "1.1"

"".join(word.split(".")).isdecimal()
>>> True

速度:

► 上述所有方法都具有相似的速度。

%timeit "".join(word.split(".")).isnumeric()
>>> 257 ns ± 12 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

%timeit "".join(word.split(".")).isdigit()
>>> 252 ns ± 11 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

%timeit "".join(word.split(".")).isdecimal()
>>> 244 ns ± 7.17 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

评论

1赞 user3711502 1/25/2022
对于所有这些示例,您正在检查 11 是否是数字,而不是 1.1
1赞 kakyo 7/26/2022
我发现这是最优雅的解决方案,尽管理论上您不是在测试浮点“值”。Python的str impl的这块真是太可惜了,太反了。
0赞 Toby Speight 11/10/2022
您需要测试更多的输入。尝试 ,这不是一个有效的数字。1.1.1
0赞 DJ Swarm 2/22/2021 #35

对不起僵尸线程帖子 - 只是想完善代码以确保完整性......

# is_number() function - Uses re = regex library
# Should handle all normal and complex numbers
# Does not accept trailing spaces. 
# Note: accepts both engineering "j" and math "i" but only the imaginary part "+bi" of a complex number a+bi
# Also accepts inf or NaN
# Thanks to the earlier responders for most the regex fu

import re

ISNUM_REGEXP = re.compile(r'^[-+]?([0-9]+|[0-9]*\.[0-9]+)([eE][-+]?[0-9]+)?[ij]?$')

def is_number(str):
#change order if you have a lot of NaN or inf to parse
    if ISNUM_REGEXP.match(str) or str == "NaN" or str == "inf": 
        return True 
    else:
        return False
# A couple test numbers
# +42.42e-42j
# -42.42E+42i

print('Is it a number?', is_number(input('Gimme any number: ')))

任意号码:+42.42e-42j

这是一个数字吗?真

0赞 Micka 7/16/2021 #36

对于我非常简单且非常常见的用例:?is this human written string with keyboard a number

我通读了大多数答案,最后得到:

def isNumeric(string):
    result = True
    try:
        x = float(string)
       result = (x == x) and (x - 1 != x)
    except ValueError:
        result = False
    return result

它将返回 False for 和 。(+-)NaN(+-)inf

你可以在这里查看: https://trinket.io/python/ce32c0e54e

1赞 Gru 8/14/2021 #37

我知道我来晚了,但想出了一个不在这里的解决方案: 此解决方案遵循 Python 中的 EAFP 原则

def get_number_from_string(value):
    try:
        int_value = int(value)
        return int_value

    except ValueError:
        return float(value)

解释:

如果字符串中的值是 a,我首先尝试将其解析为 ,它将抛出一个 .因此,我捕获了该错误并将值解析为 并返回。floatintValueErrorfloat

评论

0赞 sinekonata 10/6/2021
如果 value 是像“1.f”这样的字符串,这不会在 except 块中再次失败吗?
0赞 Gru 10/7/2021
@sinekonata,在问题中假设该数字以字符串形式存在。
1赞 Rafael Braga 1/6/2022 #38

一个快速而简单的选项是检查数据类型:

def is_number(value):
    return type(value) in [int, float]

或者,如果要测试字符串的值是否为数字:

def isNumber (value):
    return True if type(value) in [int, float] else str(value).replace('.','',1).isdigit()

测试:

>>> isNumber(1)
True

>>> isNumber(1/3)
True

>>> isNumber(1.3)
True

>>> isNumber('1.3')
True

>>> isNumber('s1.3')
False

评论

0赞 john k 1/21/2022
指数的 E 呢?
0赞 Rafael Braga 3/31/2022
是的,@johnktejik这可能是一个问题。此函数将返回 false 给字符串,例如 '1.54-e8' 和 '0X45'。对于这种数字,您可以使用正则表达式来更正问题。
1赞 Amit 11/26/2022 #39

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

与其搜索数字、数字或浮点数,不如对字母表进行否定搜索。也就是说,我们可以要求程序查看它是否不是字母表。

## 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]
0赞 Blue Phoenix 3/12/2023 #40

我的简短回答是: 可能是重复的,对不起 ... 定义 is_float(s): 如果 s.isdigit(): 返回 False 尝试: 浮子 返回 True 除了 Exception 作为 e: 返回 False

0赞 dogdog 7/12/2023 #41
def is_number(x:str):
    x = x.replace(".", "", 1)
    if x.startswith("-"):
        x = x[1:]
    return x.isdigit()

if __name__ == '__main__':
    for si in ["123.456", "-123.456", "123", "-123", "--123", "a123", "123a"]:
        print(si, is_number(si))