提问人:Daniel Goldberg 提问时间:12/10/2008 最后编辑:Karl KnechtelDaniel Goldberg 更新时间:7/12/2023 访问量:1712749
如何检查字符串是否代表数字(float 或 int)?
How do I check if a string represents a number (float or int)?
问:
如何在 Python 中检查字符串是否表示数值?
def is_number(s):
try:
float(s)
return True
except ValueError:
return False
以上有效,但看起来很笨拙。
如果要测试的内容来自用户输入,则它仍然是一个字符串,即使它表示 int
或 float
。请参阅如何以数字形式读取输入?以转换输入,以及要求用户输入,直到他们给出有效响应,以确保输入表示 int
或 float
(或其他要求),然后再继续。
答:
仅对于非负(无符号)整数,请使用 isdigit()
:
>>> a = "03523"
>>> a.isdigit()
True
>>> b = "963spam"
>>> b.isdigit()
False
适用的文档:Python2、Python3isdigit()
对于 Python 2 Unicode 字符串:isnumeric()。
评论
u'\u00b9'
:是但会引发ValueError。isdigit()
int()
u'¹'.isdigit()
True
int(u'¹')
其中,不仅丑陋而缓慢
我会对两者都提出异议。
正则表达式或其他字符串解析方法会更丑陋、更慢。
我不确定有什么能比上面更快。它调用函数并返回。Try/Catch 不会带来太多开销,因为最常见的异常是在未对堆栈帧进行广泛搜索的情况下捕获的。
问题在于,任何数值转换函数都有两种结果
- 一个数字(如果该数字有效)
- 状态代码(例如,通过 errno)或异常,以显示无法解析有效数字。
C(举个例子)通过多种方式解决这个问题。Python 清晰明确地阐述了它。
我认为你这样做的代码是完美的。
评论
try
return True
else
try
try
IsNumeric()
if is_number(s): x = float(x) else: // fail
try: x = float(x) catch TypeError: # fail
转换为浮点并捕获 ValueError 可能是最快的方法,因为 float() 专门用于此。需要字符串解析(正则表达式等)的任何其他内容都可能较慢,因为它没有针对此操作进行优化。我的 0.02 美元。
评论
这不仅丑陋而缓慢,而且看起来很笨拙。
这可能需要一些时间来适应,但这是 pythonic 的方式。正如已经指出的那样,替代方案更糟。但这样做还有一个好处:多态性。
鸭子打字背后的中心思想是“如果它像鸭子一样走路和说话,那么它就是鸭子。如果您决定需要对字符串进行子类化,以便可以更改确定是否可以将某些内容转换为浮点数的方式,该怎么办?或者,如果您决定完全测试其他对象怎么办?您可以执行这些操作,而无需更改上述代码。
其他语言通过使用接口来解决这些问题。我将保存对哪个解决方案更适合另一个线程的分析。不过,关键是 python 绝对是鸭子类型的一面,如果你打算用 Python 做很多编程,你可能不得不习惯这样的语法(但这并不意味着你当然必须喜欢它)。
您可能要考虑的另一件事是:与许多其他语言相比,Python 在抛出和捕获异常方面非常快(例如,比 .Net 快 30 倍)。哎呀,语言本身甚至抛出异常来传达非异常的正常程序条件(每次使用 for 循环时)。因此,在您注意到一个重大问题之前,我不会太担心此代码的性能方面。
评论
hasattr()
getattr()
try/except
这是我的简单方法。假设我正在遍历一些字符串,如果它们变成数字,我想将它们添加到数组中。
try:
myvar.append( float(string_to_check) )
except:
continue
如果字符串是数字,请将 myvar.apppend 替换为要对字符串执行的任何操作。这个想法是尝试使用 float() 操作并使用返回的错误来确定字符串是否为数字。
评论
在 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
评论
float()
complex()
float()
complex()
complex('(01989)')
将返回.但会失败。所以我认为使用不是一个好主意。(1989+0j)
float('(01989)')
complex
complex()
(
)
complex()
s.lstrip('-').replace('.','',1).replace('e-','',1).replace('e','',1).isdigit()
您可能需要考虑一个例外:字符串“NaN”
如果你想is_number 'NaN' 返回 FALSE,这段代码将不起作用,因为 Python 会将其转换为非数字的数字表示形式(讨论身份问题):
>>> float('NaN')
nan
否则,我实际上应该感谢你现在广泛使用的这段代码。:)
G.
评论
NaN
False
float
'inf'
inf
NaN
+
-
x-1 == x
对于小于 的大型浮点数为 true。从 Python 3.2 开始,您可以使用它来测试既不是 NaN 也不是无限大的数字,或者在此之前检查两者。inf
math.isfinite
math.isnan
math.isinf
我做了一些速度测试。假设字符串可能是一个数字,则 try/except 策略是最快的。如果字符串不太可能是数字,并且您对整数检查感兴趣,则值得进行一些测试(isdigit 加标题“-”)。 如果您有兴趣检查浮点数,则必须使用 try/except 代码 whitout 转义。
只是模仿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
伟大的蝒蛇对教廷夏皮苏斯说:“你能做的任何事情,我都能做得更好;我可以做得比你更好。
评论
!
not
float
因此,将所有这些放在一起,检查 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
评论
这个怎么样:
'3.14'.replace('.','',1).isdigit()
仅当数字字符串中有一个或没有“.”时,才会返回 true。
'3.14.5'.replace('.','',1).isdigit()
将返回 false
编辑:刚刚看到另一条评论......
可以为其他情况添加 A。如果你传递的是盐而不是任意调味品(ref:xkcd#974),这将做得很好:P.replace(badstuff,'',maxnum_badstuff)
评论
1.234e56
+1.234E+56
re.match(r'^[+-]*(0[xbo])?[0-9A-Fa-f]*\.?[0-9A-Fa-f]*(E[+-]*[0-9A-Fa-f]+)$', 'str')
应该更好地确定一个数字(但不是全部,我不是这么说)。我不建议使用它,最好使用提问者的原始代码。
我想看看哪种方法最快。总体而言,该函数给出了最佳和最一致的结果。该函数给出了最快的结果,但前提是没有触发异常 - 这意味着它的代码是最有效的,但抛出异常的开销相当大。check_replace
check_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
评论
您可以使用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
评论
s.isdecimal()
检查字符串是否为非负整数。 包括拒绝的字符。s
s.isnumeric()
int()
通过返回比 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:]), ')'
RyanN 建议
如果要为 NaN 和 Inf 返回 False,请将行更改为 x = float(s);return (x == x) 和 (x - 1 != x)。对于除 Inf 和 NaN 之外的所有浮点数,这都应返回 True
但这并不完全有效,因为对于足够大的浮点数,返回 true。例如x-1 == x
2.0**54 - 1 == 2.0**54
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()
评论
'1.5e-9'
s.replace()
s.replace('.','',1).replace('e-','',1).replace('e','',1).isdigit()
s.lstrip('-').replace('.','',1).replace('e-','',1).replace('e','',1).isdigit()
我需要确定字符串是否转换为基本类型(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)
评论
str_to_type("123e-4")
int
float("123e-4")
0.0123
str_to_type("NaN")
int
if "." not in s:
if "." not in s and "e" not in s and "N" not in s:
i = int(s); return int
f = float(s); return float
对于非数字字符串,实际上比正则表达式慢。对于有效数字的字符串,正则表达式速度较慢。因此,适当的方法取决于您的输入。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
在这两种情况下都获胜
评论
prep_code_basis
prep_code_re_method
isfloat
str(s).strip('-').replace('.','',1).isdigit()
timeit.timeit
我正在研究一个问题,这个问题导致我进入这个线程,即如何以最直观的方式将数据集合转换为字符串和数字。在阅读原始代码后,我意识到我需要的东西在两个方面有所不同:
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
试试这个。
def is_number(var):
try:
if var == int(var):
return True
except Exception:
return False
评论
is_number('10')
为此,请执行以下操作: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
评论
1.234e56
99999999999999999999e99999999999999999999
>>> '--1234'.lstrip('-').replace('.','',1).isdigit()
我知道这特别古老,但我想补充一个答案,我相信涵盖了票数最高的答案中缺少的信息,这对任何发现它的人来说都是非常有价值的:
对于以下每种方法,如果需要接受任何输入,请将它们与计数连接起来。(假设我们使用的是整数的语音定义,而不是 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()
x.replace('.','',1).isdigit()
x.replace('.','').isdigit()
我也使用了你提到的函数,但很快我注意到字符串作为“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
使用以下它处理所有情况:-
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')
这个答案提供了分步指南,其中有查找字符串的示例:
- 正整数
- 正/负 - 整数/浮点数
- 如何在检查数字时丢弃“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 返回。例如:==
False
nan
# `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
函数版本。
评论
我也有类似的问题。我不想定义 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]
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
评论
1e6
输入可能如下:
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
评论
ast
is_numeric("String 1")
此代码使用正则表达式处理指数、浮点数和整数。
return True if str1.lstrip('-').replace('.','',1).isdigit() or float(str1) else False
评论
我认为您的解决方案很好,但是有一个正确的正则表达式实现。
似乎确实有很多对这些答案的正则表达式的讨厌,我认为这是不合理的,正则表达式可以相当干净、正确和快速。这真的取决于你想做什么。最初的问题是你如何“检查一个字符串是否可以表示为一个数字(浮点数)”(根据你的标题)。据推测,一旦您检查了数字/浮点值是否有效,您就会希望使用它,在这种情况下,您的 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
评论
用户助手功能:
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 = 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
如果字符串中的所有字符都是数字字符,则返回, 否则,至少有一个字符。数值的 字符包括数字字符,以及具有 Unicode 数值属性,例如 U+2155、VULGAR FRACTION ONE 第五。从形式上讲,数字字符是具有属性值的字符 Numeric_Type=数字,Numeric_Type=十进制或 Numeric_Type=数字。
True
False
如果字符串中的所有字符都是十进制字符,则返回 否则,至少有一个字符。十进制字符 是那些可以用来形成以 10 为基数的数字,例如 U+0660, 阿拉伯语-印度语数字零。从形式上讲,十进制字符是一个字符 在Unicode通用类别“Nd”中。
True
False
两者都可用于 Python 3.0 中的字符串类型。
在浮点数的最一般情况下,需要处理整数和小数。让我们以字符串为例。"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.1.1
对不起僵尸线程帖子 - 只是想完善代码以确保完整性......
# 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
这是一个数字吗?真
对于我非常简单且非常常见的用例:?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
我知道我来晚了,但想出了一个不在这里的解决方案: 此解决方案遵循 Python 中的 EAFP 原则
def get_number_from_string(value):
try:
int_value = int(value)
return int_value
except ValueError:
return float(value)
解释:
如果字符串中的值是 a,我首先尝试将其解析为 ,它将抛出一个 .因此,我捕获了该错误并将值解析为 并返回。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 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]
我的简短回答是: 可能是重复的,对不起 ... 定义 is_float(s): 如果 s.isdigit(): 返回 False 尝试: 浮子 返回 True 除了 Exception 作为 e: 返回 False
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))
上一个:将浮点数限制为小数点后两位
评论
x = float('0.00'); if x: use_float(x);
None
try catch