我正在使用this代码来评估字符串中的数学表达式。它有效:
#!/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
答案 0 :(得分:6)
它失败的原因是你从数学模块导入的函数不是函数内的局部变量;他们是全球性的。因此,当您读取locals()并插入dict时,它会为每一个插入None。如果您删除get(key, None)
并直接访问locals()[key]
,则会看到此消息。
更好的方法是在数学模块上使用getattr。 import math
(不是from math import *
),然后执行safe_dict = dict((k, getattr(math, k)) for k in safe_list)
。
答案 1 :(得分:3)
在calculate()
函数中,locals()
不包含从math
导入的函数。因此,safe_dict
填充了大量None
。
您可以在safe_dict
之外构建calculate()
,如果您多次拨打calculate()
,也可以提高效果。
答案 2 :(得分:1)
这可能是因为'math'
中有safe_list
,而math
是一个模块。对我来说,似乎eval
正在做math()
,这会导致它阻碍它的运作方式。
尝试从'math'
移除safe_list
,看看是否有帮助。
旁注:我不确定这是做你想做的最好的方法。我认为需要改变设计。