如何检查字符串是否代表数字(浮点数或整数)?

如何检查字符串是否代表Python中的数值?

def is_number(s):try:float(s)return Trueexcept ValueError:return False

上面的作品,但它似乎笨拙。


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

1636776 次浏览

对于非负(无符号)整数,使用#0

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

isdigit()的文档:python2python3

对于Python 2 Unicode字符串:#0.

这不仅丑陋而且缓慢

我对两者都有异议。

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

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

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

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

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

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

转换为浮点数并捕获ValueError可能是最快的方法,因为浮点数()就是专门为此而设计的。任何其他需要字符串解析(正则表达式等)的东西都可能会比较慢,因为它没有针对此操作进行调整。我的0.02美元。

它不仅丑陋而缓慢,而且看起来笨重。

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

鸭子类型背后的核心思想是“如果它像鸭子一样走路和说话,那么它就是一只鸭子”。如果你决定需要对string进行子类化,这样你就可以改变确定某个东西是否可以转换为浮点数的方式,该怎么办?或者如果你决定完全测试其他对象,该怎么办?你可以在不改变上述代码的情况下完成这些事情。

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

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

这是我的简单方法。假设我正在循环浏览一些字符串,如果它们是数字,我想将它们添加到数组中。

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

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

在Alfe指出您不需要单独检查浮点数作为复杂句柄后更新:

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

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

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

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

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

>>> float('NaN')nan

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

G.

我做了一些速度测试。假设如果字符串可能是一个数字,尝试/除外策略是最快的可能。如果字符串不太可能是一个数字,你对整数感兴趣检查,值得做一些测试(isdigit加标题'-')。如果您有兴趣检查浮点数,则必须使用尝试/除外代码空白转义。

只是模仿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',因为它仍然是一个值类型。没有更好,因为它表示失败。当然,如果您想要不同的东西,您可以将失败参数更改为任何您想要的。

要扩展浮点数以包含“parse()”和“try_parse()”,您需要对“浮点数”类进行monkeypatch以添加这些方法。

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

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

旁注:我个人更喜欢称之为猴子冲孔,因为当我这样做的时候,感觉就像是在滥用语言,但是YMMV。

用法:

float.parse('giggity') // throws TypeExceptionfloat.parse('54.3') // returns the scalar value 54.3float.tryParse('twank') // returns Nonefloat.tryParse('32.2') // returns the scalar value 32.2

伟大的圣人Pythonas对罗马教廷说:“你能做的任何事,我都能做得更好;我能比你做得更好。

所以把它们放在一起,检查南,无穷大和复数(看起来它们是用j指定的,而不是i,即1+2j),结果是:

def is_number(s):try:n=str(float(s))if n == "nan" or n=="inf" or n=="-inf" : return Falseexcept ValueError:try:complex(s) # for complexexcept ValueError:return Falsereturn True

这个怎么样:

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

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

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

将返回false

编辑:刚看到另一条评论…如果你正在传递盐而不是任意调味品(参考:xkcd#974),这将做得很好:P

我想看看哪种方法最快。总的来说,check_replace函数给出了最好和最一致的结果。最快的结果是check_exception函数给出的,但前提是没有触发异常——这意味着它的代码效率最高,但抛出异常的开销相当大。

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

huge_number = float('1e+100')

以下是基准代码:

import time, re, random, string
ITERATIONS = 10000000
class Timer:def __enter__(self):self.start = time.clock()return selfdef __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 Trueexcept 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.688639check_regexp with bad floats: 11.624862check_regexp with strings: 11.349414check_replace with good floats: 4.419841check_replace with bad floats: 4.294909check_replace with strings: 4.086358check_exception with good floats: 3.276668check_exception with bad floats: 13.843092check_exception with strings: 15.786169

以下是2017 MacBook Pro 13上Python 3.6.5的结果:

check_regexp with good floats: 13.472906000000009check_regexp with bad floats: 12.977665000000016check_regexp with strings: 12.417542999999995check_replace with good floats: 6.011045999999993check_replace with bad floats: 4.849356check_replace with strings: 4.282754000000011check_exception with good floats: 6.039081999999979check_exception with bad floats: 9.322753000000006check_exception with strings: 9.952595000000002

以下是2017年MacBook Pro 13上PyPy 2.7.13的结果:

check_regexp with good floats: 2.693217check_regexp with bad floats: 2.744819check_regexp with strings: 2.532414check_replace with good floats: 0.604367check_replace with bad floats: 0.538169check_replace with strings: 0.598664check_exception with good floats: 1.944103check_exception with bad floats: 2.449182check_exception with strings: 2.200056

你可以使用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

你可以通过返回比True和False更有用的值来以一种有用的方式泛化异常技术。例如,这个函数将引号放在字符串中,但只留下数字。这正是我需要的快速而脏的过滤器来为R创建一些变量定义。

import sys
def fix_quotes(s):try:float(s)return sexcept 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:]), ')'

RyanN建议

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

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

太长别读最好的解决方案是s.replace('.','',1).isdigit()

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

def is_number_tryexcept(s):""" Returns True if string is a number. """try:float(s)return Trueexcept ValueError:return False       
import redef 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方法是正确处理科学符号的唯一方法。

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"不支持:')对于函数中的f:如果不是f(科学1):print('\t-', f.姓名

    print('科学符号“1e50”不支持:')对于函数中的f:如果不是f(科学2):print('\t-', f.姓名

科学符号“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_matchfrom re import compile as re_compile
def is_number_tryexcept(s):""" Returns True if string is a number. """try:float(s)return Trueexcept 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()

输入图片描述

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

def str_to_type (s):""" Get possible cast type for a string
Parameters----------s : string
Returns-------float,int,str,bool : typeDepending on what it can be cast to
"""try:f = float(s)if "." not in s:return intreturn floatexcept ValueError:value = s.upper()if value == "TRUE" or value == "FALSE":return boolreturn type(s)

示例

str_to_type("true") # boolstr_to_type("6.0") # floatstr_to_type("6") # intstr_to_type("6abc") # strstr_to_type(u"6abc") # unicode

您可以捕获类型并使用它

s = "6.0"type_ = str_to_type(s) # floatf = type_(s)

对于非数字字符串,try: except:实际上比正则表达式慢。对于有效数字字符串,regex更慢。因此,适当的方法取决于您的输入。

如果你发现自己处于性能绑定状态,你可以使用一个名为快数的新第三方模块,它提供了一个名为isflow的函数。完全披露,我是作者。我已经在下面的时间中包含了它的结果。


from __future__ import print_functionimport timeit
prep_base = '''\x = 'invalid'y = '5402'z = '4.754e3''''
prep_try_method = '''\def is_number_try(val):try:float(val)return Trueexcept ValueError:return False
'''
prep_re_method = '''\import refloat_match = re.compile(r'[-+]?\d*\.?\d+(?:[eE][-+]?\d+)?$').matchdef 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 secondsTry with integer strings 0.375686168671 secondsTry with float strings 0.369210958481 seconds
Regex with non-number strings 0.748660802841 secondsRegex with integer strings 1.02021503448 secondsRegex with float strings 1.08564686775 seconds
fastnumbers with non-number strings 0.174362897873 secondsfastnumbers with integer strings 0.179651021957 secondsfastnumbers with float strings 0.20222902298 seconds

如你所见

  • try: except:对于数字输入很快,但对于无效输入非常慢
  • 当输入无效时,regex非常有效
  • fastnumbers在这两种情况下获胜

我当时正在解决一个问题,这个问题让我想到了这个线程,即如何以最直观的方式将数据集合转换为字符串和数字。阅读原始代码后,我意识到我需要的有两种不同:

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

2-我想要一个数字或字符串结果粘贴到数据结构中

所以我修改了原始代码来生成这个导数:

def string_or_number(s):try:z = int(s)return zexcept ValueError:try:z = float(s)return zexcept ValueError:return s

试试这个。

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

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

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

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

x.isdigit()检查x是否为整数效果很好。

x.replace('-','').isdigit()检查x是否为负数效果很好。(签入第一个位置)

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

x.replace(':','').isdigit()#36825;检查x是否是一个比值。

x.replace('/','',1).isdigit()可以很好地检查x是否是分数。

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

def is_float(text):try:float(text)# check for nan/infinity etc.if text.isalpha():return Falsereturn Trueexcept ValueError:return False

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

import rea=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')

这个答案提供了一步一步的指导,具有查找字符串的示例的函数是:

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

检查字符串是否为积极整数

您可以使用#0来检查给定的字符串是否为积极整数。

样本结果:

# 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

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

def is_number(n):try:float(n)   # Type-casting the string to `float`.# If string is not a valid `float`,# it'll raise `ValueError` exceptionexcept ValueError:return Falsereturn True

示例运行:

>>> is_number('123')    # positive integer numberTrue
>>> is_number('123.4')  # positive float numberTrue 
>>> is_number('-123')   # negative integer numberTrue
>>> is_number('-123.4') # negative `float` numberTrue
>>> is_number('abc')    # `False` for "some random" stringFalse

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

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

>>> is_number('NaN')True

为了检查数字是否为“NaN”,您可以使用#0作为:

>>> import math>>> nan_num = float('nan')
>>> math.isnan(nan_num)True

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

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

因此,上面的函数#0可以更新为#2返回#1为:

def is_number(n):is_number = Truetry:num = float(n)# check for "nan" floatsis_number = num == num   # or use `math.isnan(num)`except ValueError:is_number = Falsereturn is_number

示例运行:

>>> is_number('Nan')   # not a number "Nan" stringFalse
>>> is_number('nan')   # not a number string "nan" with all lower casedFalse
>>> is_number('123')   # positive integerTrue
>>> is_number('-123')  # negative integerTrue
>>> is_number('-1.12') # negative `float`True
>>> is_number('abc')   # "some random" stringFalse

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

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

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

给定我们不能真正将浮点数(s)与isFloat(s)函数分开:这两个结果应该由同一个函数返回。此外,如果浮点数失败,整个过程都会失败,而不仅仅是忽略有问题的元素。另外,“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]
import redef is_number(num):pattern = re.compile(r'^[-+]?[-0-9]\d*\.\d*|[-+]?\.?[0-9]\d*$')result = pattern.match(num)if result:return Trueelse: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

输入可能如下:

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


1-一般输入:

这个函数的输入可以是一切!

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

is_numeric函数

import astimport numbersdef is_numeric(obj):if isinstance(obj, numbers.Number):return Trueelif isinstance(obj, str):nodes = list(ast.walk(ast.parse(obj)))[1:]if not isinstance(nodes[0], ast.Expr):return Falseif not isinstance(nodes[-1], ast.Num):return Falsenodes = 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 Falseelse:if not isinstance(nodes[i], (ast.USub, ast.UAdd)):return Falsereturn Trueelse: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 Trueif isinstance(obj, int):return Falseelif isinstance(obj, str):nodes = list(ast.walk(ast.parse(obj)))[1:]if not isinstance(nodes[0], ast.Expr):return Falseif not isinstance(nodes[-1], ast.Num):return Falseif not isinstance(nodes[-1].n, float):return Falsenodes = nodes[1:-1]for i in range(len(nodes)):if i % 2 == 0:if not isinstance(nodes[i], ast.UnaryOp):return Falseelse:if not isinstance(nodes[i], (ast.USub, ast.UAdd)):return Falsereturn Trueelse: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

这段代码处理指数、浮点数和整数,而不使用正则表达式。

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

我认为你的解决方案很好,但有一个正确的regexp实现。

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

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

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

不管怎样,没有更多的信息,这里有一个正则表达式,我相信它涵盖了所有的int和浮点数当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 floatsFLOAT_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  <- +42True  <- +42.42False <- +42.42.22True  <- +42.42e22True  <- +42.42E-22False <- +42.42e-22.8True  <- .42False <- 42nope

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

check_regexp with good floats: 18.001921check_regexp with bad floats: 17.861423check_regexp with strings: 17.558862check_correct_regexp with good floats: 11.04428check_correct_regexp with bad floats: 8.71211check_correct_regexp with strings: 8.144161check_replace with good floats: 6.020597check_replace with bad floats: 5.343049check_replace with strings: 5.091642check_exception with good floats: 5.201605check_exception with bad floats: 23.921864check_exception with strings: 23.755481

用户助手功能:

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)])
def is_float(s):if s is None:return False
if len(s) == 0:return False
digits_count = 0dots_count = 0signs_count = 0
for c in s:if '0' <= c <= '9':digits_count += 1elif c == '.':dots_count += 1elif c == '-' or c == '+':signs_count += 1else:return False
if digits_count == 0:return False
if dots_count > 1:return False
if signs_count > 1:return False
return True

str.isnumeric()

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

str.isdecimal()

如果字符串中的所有字符都是十进制字符并且至少有一个字符,否则False。十进制字符是那些可以用来形成基数10的数字,例如U+0660,ARABIC-INDIC DIGIT ZERO。形式上,十进制字符是一个字符在Unicode常规类别“Nd”中。

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

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

我会尝试以下方法之一:

1.>是数值

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)

对不起僵尸线程帖子-只是想完善代码的完整性…

# 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 parseif ISNUM_REGEXP.match(str) or str == "NaN" or str == "inf":return Trueelse: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

-是个数字吗?-没错

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

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

def isNumeric(string):result = Truetry:x = float(string)result = (x == x) and (x - 1 != x)except ValueError:result = Falsereturn result

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

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

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

def get_number_from_string(value):try:int_value = int(value)return int_value
except ValueError:return float(value)

说明:

如果字符串中的值是float,我首先尝试将其解析为int,它将抛出ValueError。因此,我捕获该错误并将值解析为float并返回。

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

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

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

而不是搜索数字,数字或浮点数,我们可以对字母进行负搜索。即,我们可以要求程序查看它是否不是字母表。

## Check whether it is not alpha rather than checking if it is digitprint(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 numberCase_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 numberCase_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 reCompiledPattern = 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 numberCase_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]