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
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
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
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:]), ')'
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__)
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()
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)
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
# `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
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 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
>>> 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
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 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
# 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: ')))
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]