Python相当于atoi / atof

时间:2009-11-03 06:02:24

标签: python

Python喜欢提高异常,这通常很棒。但是我正面临着一些我迫切希望使用C的atoi / atof语义转换为整数的字符串 - 例如“3 of 12”,“3/12”,“3/12”的atoi都应该变为3; atof(“3.14秒”)应变为3.14; atoi(“ - 99得分”)应该变成-99。 Python当然有atoi和atof函数,它们的行为与atoi和atof完全不同,就像Python自己的int和float构造函数一样。

我到目前为止所做的最好的,真的很丑,很难扩展到各种浮动格式:

value = 1
s = str(s).strip()
if s.startswith("-"):
    value = -1
    s = s[1:]
elif s.startswith("+"):
    s = s[1:]
try:
    mul = int("".join(itertools.takewhile(str.isdigit, s)))
except (TypeError, ValueError, AttributeError):
    mul = 0
return mul * value

6 个答案:

答案 0 :(得分:37)

如果您非常希望获得c atoi的功能,为什么不直接使用它?例如,在我的Mac上,

>>> import ctypes, ctypes.util
>>> whereislib = ctypes.util.find_library('c')
>>> whereislib
'/usr/lib/libc.dylib'
>>> clib = ctypes.cdll.LoadLibrary(whereislib)
>>> clib.atoi('-99foobar')
-99

在Linux,Windows等中,相同的代码应该可以工作,除非您检查whereislib时会看到不同的路径(仅在真正的,非常特殊的安装中,此代码无法找到C运行时库)。

如果您热衷于避免直接使用C库,我猜您可以获取相关的前缀,例如使用r'\s*([+-]?\d+)'之类的RE,然后尝试使用int

答案 1 :(得分:7)

我认为迭代版本比递归版本

更好
# Iterative
def atof(s):
    s,_,_=s.partition(' ') # eg. this helps by trimming off at the first space
    while s:
        try:
            return float(s)
        except:
            s=s[:-1]
    return 0.0

# Recursive
def atof(s):
    try:
        return float(s)
    except:
        if not s:
            return 0.0
        return atof(s[:-1])


print atof("3 of 12")
print atof("3/12")
print atof("3 / 12")
print atof("3.14 seconds")
print atof("314e-2 seconds")
print atof("-99 score")
print atof("hello world")

答案 2 :(得分:6)

也许使用快速正则表达式只抓取可以被视为数字的字符串的第一部分?有点像...

-?[0-9]+(?:\.[0-9]+)?

用于浮动和仅用于注入,

-?[0-9]+

答案 3 :(得分:3)

使用正则表达式执行此操作非常简单:

>>> import re
>>> p = re.compile(r'[^\d-]*(-?[\d]+(\.[\d]*)?([eE][+-]?[\d]+)?)')
>>> def test(seq):
        for s in seq:
            m = p.match(s)
            if m:
                result = m.groups()[0]
                if "." in result or "e" in result or "E" in result:
                    print "{0} -> {1}".format(s, float(result))
                else:
                    print '"{0}" -> {1}'.format(s, int(result))
            else:
                print s, "no match"

>>> test(s)
"1 0" -> 1
"3 of 12" -> 3
"3 1/2" -> 3
"3/12" -> 3
3.15 seconds -> 3.15
3.0E+102 -> 3e+102
"what about 2?" -> 2
"what about -2?" -> -2
2.10a -> 2.1

答案 4 :(得分:0)

我想我会用char来做char:

def myatof(s):
    try:
        return float(s);
    except:
        last_result = None
        for i in range(1, len(s)):
            try:
                last_result = float(s[:i])
            except:
                return last_result
    return last_result

答案 5 :(得分:-1)

这个怎么样?

num=int(q.join(re.findall(r'[\d-]',s)))