Python,确定字符串是否应转换为Int或Float

时间:2013-03-12 09:24:45

标签: python type-conversion decimal-point

我想将字符串转换为最可能的数据类型:int或float。

我有两个字符串:

value1="0.80"     #this needs to be a float
value2="1.00"     #this needs to be an integer.

我如何确定value1应该是Float,而value2应该是Python中的Integer?

9 个答案:

答案 0 :(得分:21)

def isfloat(x):
    try:
        a = float(x)
    except ValueError:
        return False
    else:
        return True

def isint(x):
    try:
        a = float(x)
        b = int(a)
    except ValueError:
        return False
    else:
        return a == b

答案 1 :(得分:15)

Python float个对象有is_integer method

from ast import literal_eval
def parses_to_integer(s):
    val = literal_eval(s)
    return isinstance(val, int) or (isinstance(val, float) and val.is_integer())

答案 2 :(得分:3)

def coerce(x):
    try:
        a = float(x)
        b = int(x)
        if a != b:
            return a
        else:
            return b
    except:
        raise ValueError("failed to coerce str to int or float")

答案 3 :(得分:1)

lineVal = ['1850', '-0.373', '-0.339', '-0.425']

lineVal2 = [ float(x) if re.search(r'\.',x) else int(x) for x in lineVal ]

LineVal2 output ==> [1850, -0.373, -0.339, -0.425]

我是新蜜蜂,我尝试过,似乎对我有用。

答案 4 :(得分:0)

我必须处理确保' 1.0'转换为' 1'当我试图确定两个XML文档之间的差异时。所以我写了这个函数来帮助我。我还认为,当所讨论的字符串文字是' True'时,其他一些解决方案将会失败。或者'错误'。无论如何,这个功能对我来说非常有效。我希望它对你也有帮助。

from ast import literal_eval

def convertString(s):
    '''
    This function will try to convert a string literal to a number or a bool
    such that '1.0' and '1' will both return 1.

    The point of this is to ensure that '1.0' and '1' return as int(1) and that
    'False' and 'True' are returned as bools not numbers.

    This is useful for generating text that may contain numbers for diff
    purposes.  For example you may want to dump two XML documents to text files
    then do a diff.  In this case you would want <blah value='1.0'/> to match
    <blah value='1'/>.

    The solution for me is to convert the 1.0 to 1 so that diff doesn't see a
    difference.

    If s doesn't evaluate to a literal then s will simply be returned UNLESS the
    literal is a float with no fractional part.  (i.e. 1.0 will become 1)

    If s evaluates to float or a float literal (i.e. '1.1') then a float will be
    returned if and only if the float has no fractional part.

    if s evaluates as a valid literal then the literal will be returned. (e.g.
    '1' will become 1 and 'False' will become False)
    '''


    if isinstance(s, str):
        # It's a string.  Does it represnt a literal?
        #
        try:
            val = literal_eval(s)
        except:
            # s doesn't represnt any sort of literal so no conversion will be
            # done.
            #
            val = s
    else:
        # It's already something other than a string
        #
        val = s

    ##
    # Is the float actually an int? (i.e. is the float 1.0 ?)
    #
    if isinstance(val, float):
        if val.is_integer(): 
            return int(val)

        # It really is a float
        return val

    return val

此功能的单元测试输出产生:

convertString("1")=1; we expect 1
convertString("1.0")=1; we expect 1
convertString("1.1")=1.1; we expect 1.1
convertString("010")=8; we expect 8
convertString("0xDEADBEEF")=3735928559; we expect 3735928559
convertString("hello")="hello"; we expect "hello"
convertString("false")="false"; we expect "false"
convertString("true")="true"; we expect "true"
convertString("False")=False; we expect False
convertString("True")=True; we expect True
convertString(sri.gui3.xmlSamples.test_convertString.A)=sri.gui3.xmlSamples.test_convertString.A; we expect sri.gui3.xmlSamples.test_convertString.A
convertString(<function B at 0x7fd9e2f27ed8>)=<function B at 0x7fd9e2f27ed8>; we expect <function B at 0x7fd9e2f27ed8>
convertString(1)=1; we expect 1
convertString(1.0)=1; we expect 1
convertString(1.1)=1.1; we expect 1.1
convertString(3735928559)=3735928559; we expect 3735928559
convertString(False)=False; we expect False
convertString(True)=True; we expect True

单元测试代码如下:

import unittest

# just  class for testing that the class gets returned unmolested.
#
class A: pass

# Just a function
#
def B(): pass

class Test(unittest.TestCase):


    def setUp(self):
        self.conversions = [
            # input      | expected
            ('1'         ,1         ),
            ('1.0'       ,1         ), # float with no fractional part
            ('1.1'       ,1.1       ),
            ('010'       ,8         ), # octal
            ('0xDEADBEEF',0xDEADBEEF), # hex
            ('hello'     ,'hello'   ),
            ('false'     ,'false'   ),
            ('true'      ,'true'    ),
            ('False'     ,False     ), # bool
            ('True'      ,True      ), # bool
            (A           ,A         ), # class
            (B           ,B         ), # function
            (1           ,1         ),
            (1.0         ,1         ), # float with no fractional part
            (1.1         ,1.1       ),
            (0xDEADBEEF  ,0xDEADBEEF),
            (False       ,False     ),
            (True        ,True      ),
        ]


    def testName(self):
        for s,expected in self.conversions:
            rval = convertString(s)
            print 'convertString({s})={rval}; we expect {expected}'.format(**locals())
            self.assertEqual(rval, expected)


if __name__ == "__main__":
    #import sys;sys.argv = ['', 'Test.testName']
    unittest.main()

答案 5 :(得分:0)

这是使用eval()的有趣解决方案。注意:使用eval非常危险,不建议在生产环境或eval()可能接收用户输入的任何地方使用!认为这只是学术上有趣的答案。

def get_string_type(x):
    if type(x) != str:
        raise ValueError('Input must be a string!')
    try:
        string_type = type(eval(x))
    except NameError:
        string_type = str
    return string_type

由于Eval将字符串视为原始代码,因此适用于您可以输入到repl中的任何类型。实施例

>>> from decimal import Decimal
>>> my_test_string = 'Decimal(0.5)'
>>> type(my_test_string)
<class 'str'>
>>> get_string_type(my_test_string)
<class 'decimal.Decimal'>

答案 6 :(得分:0)

另一种方法是使用正则表达式,如下所示:

import re
def parse_str(num):
    """
    Parse a string that is expected to contain a number.
    :param num: str. the number in string.
    :return: float or int. Parsed num.
    """
    if not isinstance(num, str): # optional - check type
        raise TypeError('num should be a str. Got {}.'
                        .format(type(num)))
    if re.compile('^\s*\d+\s*$').search(num):
        return int(num)
    if re.compile('^\s*(\d*\.\d+)|(\d+\.\d*)\s*$').search(num):
        return float(num)
    raise ValueError('num is not a number. Got {}.'.format(num)) # optional

关于正则表达式模式的注意事项

^      beginning of string
$      end of string
\s*    none or more spaces
\d+    one or many digits
\d*    none or many digits
\.     literal dot
|      or

测试

print(parse_str('1'))
print(parse_str('999'))
print(parse_str('1.2'))
print(parse_str('.3'))
print(parse_str('4.'))
print(parse_str('12.34'))
print(parse_str('    0.5    '))
print(parse_str('XYZ'))

结果

1
999
1.2
0.3
4.0
12.34
0.5
ValueError: num is not a number. Got XYZ.

答案 7 :(得分:0)

我开始考虑到请求是将以字符串形式存储的数字转换为凋零或,以最严格的数据类型为准。以下函数满足请求(但不检查输入是否为有效值,即数字而不是字母字符)。

str_to_float_or_int()将以字符串形式存储的数字转换为<float><int>。尽管所有整数都可以是浮点数,但在满足以下条件时,将尽可能返回<int>来满足“转换为最严格的数据类型”标准:

  • 输入=整数。
  • input =尾数为0('1.0')的特征
  • input =没有尾数('1.')的特征

此技术使用str.isdecimal()确定字符串是否为值(相对于null),并使用<str>.split(".")方法将字符串值(候选数字)解析为两部分:

  1. 整数=小数点前的数字
  2. Mantissa =小数点后的数字

内置的<str>.split(".")方法返回一个列表。在这种情况下,列表具有以下格式:[integer, mantissa]

注意:从技术上讲,这里真正使用术语“整数” 指“特征”。我使用“整数”是因为 它具有较少的字符,因此更易于在编码中使用。

def str_to_float_or_int(value_str, ShowExtended=False):
    # Convert a number stored as a string to a <float> or an <int> 
    # whichever is the "tightest" data type. 

    # Default condition is that the number is a <float>
    isfloat = True
    value = float(value_str)
    numberParsed = value_str.split(".")
    if len(numberParsed) > 1:
        integer = numberParsed[0]
        mantissa = numberParsed[1]
        if integer.isdecimal() and mantissa.isdecimal():
            if int(mantissa) == 0:
                # value is an integer; mantissa is 0
                isfloat = False
                value = int(integer)
            elif integer.isdecimal():
                # value is an integer because a value is only
                # returned for 'integer' variable by .split(), 
                # the returned mantissa value is null.
                isfloat = False
                value = int(integer)
        else:
            # value is an integer because .split() returned
            # a single value list.
            isfloat = False
            value = int(value_str)
        if ShowExtended:
            print("testValue: " + value_str + " | splits into: ", 
                   numberParsed,"\n value: ", value)
            if isfloat:
                print("It's a <float> (;o)\n")
            else:
                print("It's an <int> {:o)~\n")
        return value

从控制台运行脚本以测试str_to_float_or_int()


testValues = ["0.80", "1.00", "5", ".1", "4."]
print("\n-----------------------------------------------\n" +
        "| Testcase:  ", testValues, " |\n" +
        "-----------------------------------------------")
for number in testValues:
    str_to_float_or_int(number, ShowExtended=True)

输出结果(从控制台复制)


>   ---------------------------------------------------
>   |  Testcase:   ['0.80', '1.00', '5', '.1', '4.']  |
>   ---------------------------------------------------
>   testValue: 0.80 | splits into:  ['0', '80']
>   value:  0.8
>   It's a <float> (;o)
>   
>   testValue: 1.00 | splits into:  ['1', '00']
>   value:  1
>   It's an <int> {:o)~
>   
>   testValue: 5 | splits into:  ['5']
>   value:  5
>   It's an <int> {:o)~
>   
>   testValue: .1 | splits into:  ['', '1']
>   value:  0.1
>   It's a <float> (;o)
>
>   testValue: 4. | splits into:  ['4', '']
>   value:  4
>   It's an <int> {:o)~

答案 8 :(得分:0)

这个简单的函数可以解决问题,您只需要“解决方案”代码块。

intOrfloat.py:

import sys
def NumberType(argv):
    Number = argv[1]
    try:
        float(Number)   # Exception if not a number
        ################ Solution ################
        if '.' not in Number:
            return '%s is Integer'%(Number)
        if int(Number.split('.')[1]) > 0:
            return '%s is Float'%(Number)
        else:
            return '%s is Integer'%(Number)
        ##########################################
    except Exception as e:
        return '%s is Text...'%(Number)
if __name__ == '__main__':
    print(NumberType(sys.argv))

测试:

>python intOrfloat.py 0.80
0.80 is Float

>python intOrfloat.py 1.00
1.00 is Integer

>python intOrfloat.py 9999999999999999
9999999999999999 is Integer

因此,无需担心整数的大小。

'.' not in Number              # number without decimal must be an integer
Number.split('.')              # split into [integer String, decimal String]
Number.split('.')[1]           # get decimal String
int(Number.split('.')[1])      # convert it into decimal Number
int(Number.split('.')[1]) > 0  # decimal Number > 0 = Float; Otherwise, Integer