2

我正在使用代码来评估字符串中的数学表达式。它有效:

#!/usr/bin/env python
from __future__ import division
from math import *

expression = raw_input()

# Math functions
safe_list = ['math', 'factorial', 'acos', 'asin', 'atan', 'atan2', 'ceil', 'cos', 'cosh', 'degrees', 'e', 'exp', 'fabs', 'floor', 'fmod', 'hypot', 'log', 'log10', 'modf', 'pi', 'pow', 'radians', 'sin', 'sinh', 'sqrt', 'tan', 'tanh'] 

# Create safe directory
safe_dict = dict([(key, locals().get(key, None)) for key in safe_list]) 
safe_dict['abs'] = abs

result = eval(expression, {"__builtins__": None}, safe_dict)
print result

我将它包装在这样的函数中:

#!/usr/bin/env python
from __future__ import division
from math import *

def calculate(expression):
    # Math functions
    safe_list = ['math', 'factorial', 'acos', 'asin', 'atan', 'atan2', 'ceil', 'cos', 'cosh', 'degrees', 'e', 'exp', 'fabs', 'floor', 'fmod', 'hypot', 'log', 'log10', 'modf', 'pi', 'pow', 'radians', 'sin', 'sinh', 'sqrt', 'tan', 'tanh'] 

    # Create safe directory
    safe_dict = dict([(key, locals().get(key, None)) for key in safe_list]) 
    safe_dict['abs'] = abs

    result = eval(expression, {"__builtins__": None}, safe_dict)
    if isinstance(result, float) and result.is_integer():
        result = int(result)
    print result

expr = raw_input()
calculate(expr)

它仍然适用于基本操作,但其中定义的功能safe_dict都不起作用。5**5适用于这两个程序,但适用sin(pi)于第一个代码示例,它不适用于第二个代码示例。追溯是

Traceback (most recent call last):
  File "stack.py", line 20, in <module>
    calculate(expression)
  File "stack.py", line 14, in calculate
    result = eval(expression, {"__builtins__": None}, safe_dict)
  File "<string>", line 1, in <module>
TypeError: 'NoneType' object is not callable
4

3 回答 3

7

它失败的原因是您从数学模块导入的函数不是函数内部的局部变量;它们是全球性的。因此,当您阅读 locals() 并插入到字典中时,它会为每一个插入 None 。如果您删除get(key, None)并直接访问,您会看到这一点locals()[key]

更好的方法是在数学模块上使用 getattr。做import math(不from math import *)然后做safe_dict = dict((k, getattr(math, k)) for k in safe_list)

于 2012-07-10T18:29:37.637 回答
3

在您的calculate()函数中,locals()不包括从math. 因此, safe_dict人口众多None

您可以构建 . 的safe_dict外部calculate(),如果您多次调用calculate().

于 2012-07-10T18:29:00.983 回答
1

这可能是因为您有'math'in safe_list,并且math是一个模块。对我来说,这似乎eval是在做math(),这将导致它窒息它正在做的事情。

尝试从中删除'math'safe_list看看是否有帮助。

附带说明:我不确定这真的是做你想做的事情的最佳方式。我认为需要进行设计更改。

于 2012-07-10T18:25:45.487 回答