6

如果我有一个字符串

equation = "1+2+3+4"

如何将其更改为 int 并将答案等同起来?我在想这样的事情,但它会给出一个错误。

answer = (int)equation
print(answer)

方程可以包含+-*/

4

4 回答 4

7

如果您准备接受风险,即您可能让敌对用户在您的机器上运行他们喜欢的任何东西,您可以使用eval()

>>> 等式 = "1+2+3+4"
>>> 评估(方程)
10

如果您的代码只接受您控制的输入,那么这是最快和最简单的解决方案。如果您需要允许来自您以外的用户的一般输入,那么您需要寻找一个更具限制性的表达式评估器。

更新

感谢@roippi 把我拉起来并指出上面的代码是在调用代码的环境中执行的。因此,表达式将使用可用的局部和全局变量进行评估。像这样抑制它:

eval(equation, {'__builtins__': None})

这并没有使用eval()安全。它只是为它提供了一个干净、空旷的运行环境。敌对的用户仍然可以用软管冲洗您的系统。

于 2013-11-13T16:39:56.753 回答
5

如果我们想向世界展示一个计算器,我很想看看破解者是否可以解决这个问题:

import string

def less_dangerous_eval(equation):
    if not set(equation).intersection(string.ascii_letters + '{}[]_;\n'):
        return eval(equation)
    else:
        print("illegal character")
        return None

less_dangerous_eval('1*2/3^4+(5-6)')

返回:

3

我知道这可以通过给它错误的语法(可以用一个 try/except 块修复)或一个会占用系统中所有内存的操作来打破(try/except 捕捉这个可能更不确定),但我是目前不知道有人可以通过任何方式获得控制权。

于 2013-11-13T17:04:02.243 回答
1

如果您只有数字和加号,则此方法有效:

answer = sum(float(i) for i in equation.split('+'))

或者如果你知道它们只会是整数

answer = sum(int(i) for i in equation.split('+'))

如果您希望能够进行更多评估,我建议您做好功课:

  • 查找字符串模块(其中有 string.digits)

  • 数学模块,它有你的操作

  • 创建逻辑以正确顺序执行操作

祝你好运!

于 2013-11-13T16:38:18.350 回答
-2

我建议您使用eval并检查输入:

def evaluate(s):
    import string
    for i in s:
        if i not in "+-*/ " + string.digits:
            return False       # input is not valid
    return eval(s)

如前所述,eval它是不安全的,并且很难确保安全。我记得看到一篇非常好的博客文章解释了这一点,有人知道它是什么吗?但是ast.literal_eval是安全的,它不允许__import__等。我强烈建议尽可能使用ast.literal_eval而不是。eval不幸的是,在这种情况下这是不可能的。但是,在另一种情况下,例如您只需要支持加法和乘法的情况,您可以(并且应该)literal_eval改用它。

另一方面,如果这是打算让您学习解析的作业,那么我建议您以不同的方式进行。我知道如果我是一名教师,我会使用eval“非常聪明,但这不会帮助你通过抽象语法树的测试”来回答答案。(顺便说一句,如果您想“正确地”实现这一点,您应该看看一件事)。

于 2013-11-13T17:00:02.420 回答