我有一些 Python 代码,可以运行字符串列表,并在可能的情况下将它们转换为整数或浮点数。对整数执行此操作非常简单

if element.isdigit():
  newelement = int(element)

浮点数更难。现在我正在使用 partition('.') 分割字符串并检查以确保一侧或两侧都是数字。

partition = element.partition('.')
if (partition[0].isdigit() and partition[1] == '.' and partition[2].isdigit()) 
    or (partition[0] == '' and partition[1] == '.' and partition[2].isdigit()) 
    or (partition[0].isdigit() and partition[1] == '.' and partition[2] == ''):
  newelement = float(element)

这是可行的,但显然 if 语句有点麻烦。我考虑的另一个解决方案是将转换包装在 try/catch 块中,然后查看它是否成功,如中所述 这个问题.

有人还有其他想法吗?对分区和 try/catch 方法的相对优点有何看法?

有帮助吗?

解决方案

我只想用..

try:
    float(element)
except ValueError:
    print "Not a float"

..它简单,它的工作原理

另一种选择是一个正则表达式:

import re
if re.match("^\d+?\.\d+?$", element) is None:
    print "Not float"

其他提示

的Python方法以检查浮动:

def isfloat(value):
  try:
    float(value)
    return True
  except ValueError:
    return False

不要被妖精躲在浮船得到位!做单元测试!

什么是,并且不是浮子可以令你感到惊讶:

Command to parse                        Is it a float?  Comment
--------------------------------------  --------------- ------------
print(isfloat(""))                      False
print(isfloat("1234567"))               True 
print(isfloat("NaN"))                   True            nan is also float
print(isfloat("NaNananana BATMAN"))     False
print(isfloat("123.456"))               True
print(isfloat("123.E4"))                True
print(isfloat(".1"))                    True
print(isfloat("1,234"))                 False
print(isfloat("NULL"))                  False           case insensitive
print(isfloat(",1"))                    False           
print(isfloat("123.EE4"))               False           
print(isfloat("6.523537535629999e-07")) True
print(isfloat("6e777777"))              True            This is same as Inf
print(isfloat("-iNF"))                  True
print(isfloat("1.797693e+308"))         True
print(isfloat("infinity"))              True
print(isfloat("infinity and BEYOND"))   False
print(isfloat("12.34.56"))              False           Two dots not allowed.
print(isfloat("#56"))                   False
print(isfloat("56%"))                   False
print(isfloat("0E0"))                   True
print(isfloat("x86E0"))                 False
print(isfloat("86-5"))                  False
print(isfloat("True"))                  False           Boolean is not a float.   
print(isfloat(True))                    True            Boolean is a float
print(isfloat("+1e1^5"))                False
print(isfloat("+1e1"))                  True
print(isfloat("+1e1.3"))                False
print(isfloat("+1.3P1"))                False
print(isfloat("-+1"))                   False
print(isfloat("(1)"))                   False           brackets not interpreted
'1.43'.replace('.','',1).isdigit()

将返回true仅当有一个或无“”在数字串。 搜索结果

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

将返回false 搜索结果

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

将返回false

如果您关心性能(我并不建议您应该这样做),那么基于尝试的方法显然是赢家(与基于分区的方法或正则表达式方法相比),只要您不期望太多无效字符串,在这种情况下它可能会更慢(可能是由于异常处理的成本)。

再说一遍,我并不是建议您关心性能,只是向您提供数据,以防您每秒执行 100 亿次此类操作或其他操作。此外,基于分区的代码不处理至少一个有效字符串。

$ ./floatstr.py
F..
partition sad: 3.1102449894
partition happy: 2.09208488464
..
re sad: 7.76906108856
re happy: 7.09421992302
..
try sad: 12.1525540352
try happy: 1.44165301323
.
======================================================================
FAIL: test_partition (__main__.ConvertTests)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "./floatstr.py", line 48, in test_partition
    self.failUnless(is_float_partition("20e2"))
AssertionError

----------------------------------------------------------------------
Ran 8 tests in 33.670s

FAILED (failures=1)

这是代码(Python 2.6,正则表达式取自 John Gietzen) 回答):

def is_float_try(str):
    try:
        float(str)
        return True
    except ValueError:
        return False

import re
_float_regexp = re.compile(r"^[-+]?(?:\b[0-9]+(?:\.[0-9]*)?|\.[0-9]+\b)(?:[eE][-+]?[0-9]+\b)?$")
def is_float_re(str):
    return re.match(_float_regexp, str)


def is_float_partition(element):
    partition=element.partition('.')
    if (partition[0].isdigit() and partition[1]=='.' and partition[2].isdigit()) or (partition[0]=='' and partition[1]=='.' and pa\
rtition[2].isdigit()) or (partition[0].isdigit() and partition[1]=='.' and partition[2]==''):
        return True

if __name__ == '__main__':
    import unittest
    import timeit

    class ConvertTests(unittest.TestCase):
        def test_re(self):
            self.failUnless(is_float_re("20e2"))

        def test_try(self):
            self.failUnless(is_float_try("20e2"))

        def test_re_perf(self):
            print
            print 're sad:', timeit.Timer('floatstr.is_float_re("12.2x")', "import floatstr").timeit()
            print 're happy:', timeit.Timer('floatstr.is_float_re("12.2")', "import floatstr").timeit()

        def test_try_perf(self):
            print
            print 'try sad:', timeit.Timer('floatstr.is_float_try("12.2x")', "import floatstr").timeit()
            print 'try happy:', timeit.Timer('floatstr.is_float_try("12.2")', "import floatstr").timeit()

        def test_partition_perf(self):
            print
            print 'partition sad:', timeit.Timer('floatstr.is_float_partition("12.2x")', "import floatstr").timeit()
            print 'partition happy:', timeit.Timer('floatstr.is_float_partition("12.2")', "import floatstr").timeit()

        def test_partition(self):
            self.failUnless(is_float_partition("20e2"))

        def test_partition2(self):
            self.failUnless(is_float_partition(".2"))

        def test_partition3(self):
            self.failIf(is_float_partition("1234x.2"))

    unittest.main()

长话短说:

  • 如果您的输入主要是字符串 转换为浮点数,则 try: except: 方法是最好的原生 Python 方法。
  • 如果您的输入主要是字符串 不能 转换为浮点数、正则表达式或者分区方法会更好。
  • 如果您 1) 不确定您的输入或需要更快的速度,2) 不介意并且可以安装第三方 C 扩展, 快速数字 效果很好。

还有另一种方法可以通过第三方模块使用,称为 快速数字 (披露,我是作者);它提供了一个名为 是浮动的. 。我采用了 Jacob Gabrielson 中概述的单元测试示例 这个答案, ,但添加了 fastnumbers.isfloat 方法。我还应该注意到,雅各布的示例并没有公正地对待正则表达式选项,因为该示例中的大部分时间都花在了全局查找上,因为点运算符......我修改了该函数以进行更公平的比较 try: except:.


def is_float_try(str):
    try:
        float(str)
        return True
    except ValueError:
        return False

import re
_float_regexp = re.compile(r"^[-+]?(?:\b[0-9]+(?:\.[0-9]*)?|\.[0-9]+\b)(?:[eE][-+]?[0-9]+\b)?$").match
def is_float_re(str):
    return True if _float_regexp(str) else False

def is_float_partition(element):
    partition=element.partition('.')
    if (partition[0].isdigit() and partition[1]=='.' and partition[2].isdigit()) or (partition[0]=='' and partition[1]=='.' and partition[2].isdigit()) or (partition[0].isdigit() and partition[1]=='.' and partition[2]==''):
        return True
    else:
        return False

from fastnumbers import isfloat


if __name__ == '__main__':
    import unittest
    import timeit

    class ConvertTests(unittest.TestCase):

        def test_re_perf(self):
            print
            print 're sad:', timeit.Timer('ttest.is_float_re("12.2x")', "import ttest").timeit()
            print 're happy:', timeit.Timer('ttest.is_float_re("12.2")', "import ttest").timeit()

        def test_try_perf(self):
            print
            print 'try sad:', timeit.Timer('ttest.is_float_try("12.2x")', "import ttest").timeit()
            print 'try happy:', timeit.Timer('ttest.is_float_try("12.2")', "import ttest").timeit()

        def test_fn_perf(self):
            print
            print 'fn sad:', timeit.Timer('ttest.isfloat("12.2x")', "import ttest").timeit()
            print 'fn happy:', timeit.Timer('ttest.isfloat("12.2")', "import ttest").timeit()


        def test_part_perf(self):
            print
            print 'part sad:', timeit.Timer('ttest.is_float_partition("12.2x")', "import ttest").timeit()
            print 'part happy:', timeit.Timer('ttest.is_float_partition("12.2")', "import ttest").timeit()

    unittest.main()

在我的机器上,输出是:

fn sad: 0.220988988876
fn happy: 0.212214946747
.
part sad: 1.2219619751
part happy: 0.754667043686
.
re sad: 1.50515985489
re happy: 1.01107215881
.
try sad: 2.40243887901
try happy: 0.425730228424
.
----------------------------------------------------------------------
Ran 4 tests in 7.761s

OK

正如您所看到的,正则表达式实际上并不像最初看起来那么糟糕,如果您确实需要速度,那么 fastnumbers 方法相当不错。

就为了各种这里是另一种方法来做到这一点。

>>> all([i.isnumeric() for i in '1.2'.split('.',1)])
True
>>> all([i.isnumeric() for i in '2'.split('.',1)])
True
>>> all([i.isnumeric() for i in '2.f'.split('.',1)])
False

编辑:我敢肯定它不会容纳浮动,虽然特别是当有一个指数的所有案件。为了解决它看起来像这样。这将返回True只val为INT的float和假,但可能比正则表达式少高性能。

>>> def isfloat(val):
...     return all([ [any([i.isnumeric(), i in ['.','e']]) for i in val],  len(val.split('.')) == 2] )
...
>>> isfloat('1')
False
>>> isfloat('1.2')
True
>>> isfloat('1.2e3')
True
>>> isfloat('12e3')
False

此正则表达式将检查科学浮点数:

^[-+]?(?:\b[0-9]+(?:\.[0-9]*)?|\.[0-9]+\b)(?:[eE][-+]?[0-9]+\b)?$

不过,我认为,最好的办法是使用解析器在一个尝试。

如果您不必担心号码的科学或其他表达式,并且只用字符串,可以是数字有或无期的工作:

<强>功能

def is_float(s):
    result = False
    if s.count(".") == 1:
        if s.replace(".", "").isdigit():
            result = True
    return result

<强> LAMBDA版本

is_float = lambda x: x.replace('.','',1).isdigit() and "." in x

示例

if is_float(some_string):
    some_string = float(some_string)
elif some_string.isdigit():
    some_string = int(some_string)
else:
    print "Does not convert to int or float."

此方式,你不会意外转换应该是什么一个int,变成浮动。

<强>简化其足以在大多数情况下,功能 is_digit(str),版本(不考虑指数表示法 “南”值):

def is_digit(str):
    return str.lstrip('-').replace('.', '').isdigit()

我以前已经提到的功能,但很快我发现字符串作为“南”,“天道酬勤”和它的变化被认为是数。所以,我建议你改进功能的版本,将返回这些类型的输入错误,并不会失败“1E3”变种:

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

尝试转换浮动。如果有错误,则打印ValueError异常。

try:
    x = float('1.23')
    print('val=',x)
    y = float('abc')
    print('val=',y)
except ValueError as err:
    print('floatErr;',err)

输出:

val= 1.23
floatErr: could not convert string to float: 'abc'

我一直在寻找一些类似的代码,但它看起来像使用try /节选是最好的方式。 下面是我使用的代码。它包括一个重试功能如果输入的是无效的。我需要检查,如果输入是大于0且如果是的话将其转换为浮点数。

def cleanInput(question,retry=False): 
    inputValue = input("\n\nOnly positive numbers can be entered, please re-enter the value.\n\n{}".format(question)) if retry else input(question)
    try:
        if float(inputValue) <= 0 : raise ValueError()
        else : return(float(inputValue))
    except ValueError : return(cleanInput(question,retry=True))


willbefloat = cleanInput("Give me the number: ")
str(strval).isdigit()

似乎是简单的。

把手存储在作为一个字符串值或整数或浮点数

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top