Pythonic方法将字符串中的所有八进制值作为整数进行评估

时间:2012-03-23 16:38:19

标签: python string eval

所以我有一个看起来像"012 + 2 - 01 + 24"的字符串。我希望能够快速(更少的代码)评估该表达式...

我可以在字符串上使用eval(),但我不希望012以八进制形式(10)表示,我希望它表示为int(12)。

我的解决方案有效,但不优雅。我有点假设有一种非常好的pythonic方法来做到这一点。

我的解决方案:

#expression is some string that looks like "012 + 2 - 01 + 24"
atomlist = []
for atom in expression.split():
    if "+" not in atom and "-" not in atom:
        atomlist.append(int(atom))
    else:
        atomlist.append(atom)
#print atomlist
evalstring = ""
for atom in atomlist:
    evalstring+=str(atom)    
#print evalstring
num = eval(evalstring)

基本上,我撕开appart字符串,然后在其中找到数字并将它们变成int,然后我用int重建字符串(基本上删除前导0,除非0是一个数字本身)。

如何做得更好?

4 个答案:

答案 0 :(得分:9)

我很想使用正则表达式删除前导零:

>>> re.sub(r'\b0+(?!\b)', '', '012 + 2 + 0 - 01 + 204 - 0')
'12 + 2 + 0 - 1 + 204 - 0'

这会在每个数字的开头删除零,除非数字完全由零组成:

  • 第一个\b匹配单词(标记)边界;
  • 0+匹配一个或多个连续的零;
  • (?!\b)negative lookahead)禁止匹配,其中零序列后跟一个标记边界。

这种方法优于基于split()的替代方案的一个优点是它不需要空格才能工作:

>>> re.sub(r'\b0+(?!\b)', '', '012+2+0-01+204-0')
'12+2+0-1+204-0'

答案 1 :(得分:5)

你可以使用lstrip()在一行中删除任何前导零:

>>> eval("".join(token.lstrip('0') for token in s.split()))
37

答案 2 :(得分:2)

我想这样做:

>>> s = '012 + 2 + 0 - 01 + 204 - 0'
>>> ' '.join(str(int(x)) if x.isdigit() else x for x in s.split())
'12 + 2 + 0 - 1 + 204 - 0'

如果你想处理它们,请使用float():)

答案 3 :(得分:1)

int不假设前导零表示八进制数:

In [26]: int('012')
Out[26]: 12

因此,您可以使用以下代码

安全地评估表达式
from operator import add, sub
from collections import deque

def mapper(item, opmap = {'+': add, '-': sub}):
    try: return int(item)
    except ValueError: pass

    return opmap[item]

stack = deque()
# if item filters out empty strings between whitespace sequences
for item in (mapper(item) for item in "012 + 2 - 01 + 24".split(' ') if item):
    if stack and callable(stack[-1]):
        f = stack.pop()
        stack.append(f(stack.pop(), item))
    else: stack.append(item)

print stack.pop()

不是单行,但它是安全的,因为你控制了所有可以执行的功能。