0

假设我有一个映射 map,它将各种字符串与数值相关联:

{['a', 1],['b', 2], ['c',5]}

我想定义一个运算,op它将分布在算术运算上。所以我希望 op 的功能如下:

op('a+b') = 3

op('b') = 2

op('a*b+c') = 7 

等等

我能想到的唯一方法就是解析字符串,记住操作,进行映射,然后进行操作。似乎有点昂贵/长,我希望可以有一个更优雅的解决方案,内置操作。

编辑:

我意识到我所说的方式对我的问题并不准确,映射没有在我的系统上定义,所以我无法定义所有可能的映射。我必须查询映射的外部来源。

4

4 回答 4

1

' 不确定你有没有想过,但 Python 允许你覆盖操作符。如果不需要解析字符串,您可以创建一个包装类并定义相关运算符以从“映射”中提取值。在这里,我使用字典并且只定义“加法”:

class V:
    values = { 'a': 1, 'b': 2, 'c': 3 }

    def __init__(self, name):
        self.name = name

    def __add__(self, other):
        return V.values[self.name] + V.values[other.name]

a = V('a')
b = V('b')

print a+b
# display 3

如果你使用字符串,你甚至可以使用eval这样的表达式(即使从安全的角度来看eval不是你最好的朋友——你永远不应该直接eval来自不受信任来源的表达式):

print eval("a+b")
# display 3
于 2013-06-21T17:45:43.547 回答
0

这是一个单行:

>>> eval('b', dict([['a', 1],['b', 2], ['c',5]]))
2
>>> eval('a+b', dict([['a', 1],['b', 2], ['c',5]]))
3
>>> eval('a*b+c', dict([['a', 1],['b', 2], ['c',5]]))
7
于 2013-06-22T08:56:40.030 回答
0
def op(eqn_str,**vars):
    for var,val in vars.items():
        eqn_str = eqn_str.replace(var,str(val))
    return eval(eqn_str)

op('a+b',a=5,b=3)
op('a+b',**{'a':5,'b':3})
my_vars = {'a':5,'b':3}
op('a+b',**my_vars)

或者更有趣

def op(eqn_str,**vars):
    eqn_str = re.sub('(a-z)','%(\\1)s',eqn_str)
    eqn_str = eqn_str.format(vars)
    return eval(eqn_str)
#called same way as above

可能是这样的......虽然 eval 总是有点粗略

真的,我同意乔恩的评论,你可能应该看看 sympy

弄清楚你需要什么钥匙,你可以做

needed_keys = [letter for letter in str_eqn if letter.isalpha()]
于 2013-06-21T17:43:29.513 回答
0

好吧,除非您想要重新发明 sympy(请参阅注释),否则您要做的是解析字符串中的数据,创建抽象语法树,获取符号并将其转换为 python 对象。这样您甚至可以尊重运营商的优先级,并且您没有使用 EVAL

我对您的最佳建议是查看这70 行要点,它显示了如何实现一个简单的计算器(不知何故您想要什么)。您只需要将您的值与字符串中的值进行匹配。

本着与我所说的相同的精神,@JFSebastian 链接了一个更好的帖子。

于 2013-06-21T17:47:08.247 回答