我正在研究一个应用程序,它允许用户通过输入一个字符串来定义一个数学函数(就像你在wolfram alpha上看到的那样)定义的范围。我使用eval()函数来解释字符串并填充y值列表(已定义的x值列表)。我只允许eval()访问一些常见的numpy数学函数和变量名'x'。Python3:与自定义字典不评估数字的eval()
该类允许我为用户输入的每个字符串创建一个对象,并创建两个列表x和y,用于使用matplotlib进行绘图。你可以运行这个MWE,看到它处理x罚函数(例如,sin(x),ln(x),3 * x等),并根据需要抛出非数学函数例如'foo'的异常。但是,给它一个数字如'3'或'4.00'会导致eval()在self.y列表中不写任何内容。您可以在代码中的各个点上打印self.y的形状,并且您会看到只要eval()运行(当输入的字符串是数字时),self.y的形状就变成()。
#!/usr/bin/env python3
import numpy as np
import matplotlib.pyplot as plt
class functionType():
def __init__(self, funcStr, xlo=0.0, xhi=10.0, res=100):
self.x = []
self.y = []
self.xlo = xlo
self.xhi = xhi
self.res = res
self.funcStr = funcStr
self.x = np.linspace(self.xlo, self.xhi, self.res)
self.safe_dict = {'np':np,
'sin':np.sin,
'cos':np.cos,
'tan':np.tan,
'arcsin':np.arcsin,
'arccos':np.arccos,
'arctan':np.arctan,
'sinh':np.sinh,
'cosh':np.cosh,
'tanh':np.tanh,
'arcsinh':np.arcsinh,
'arccosh':np.arccosh,
'arctanh':np.arctanh,
'ln':np.log,
'log10':np.log10,
'log2':np.log2,
'exp':np.exp,
'sqrt':np.sqrt,
'abs':np.fabs,
'x':self.x}
try:
self.y = eval(self.funcStr,{__builtins__:None},self.safe_dict)
except Exception:
raise Exception
def _reMakeData(self):
self.x = np.linspace(self.xlo, self.xhi, self.res)
self.safe_dict['x'] = self.x
self.y = eval(self.funcStr,{__builtins__:None},self.safe_dict)
def setXLow(self, value):
self.xlo = value
self._reMakeData()
def setXHigh(self, value):
self.xhi = value
self._reMakeData()
def setRes(self, value):
self.res = value
self._reMakeData()
def getXLow(self):
return self.xlo
def getXHigh(self):
return self.xhi
def getRes(self):
return self.res
def getData(self):
return self.x, self.y
func = input("gimme a function: ")
try:
plot1 = functionType(func)
x, y = plot1.getData()
plt.plot(x,y,marker='',color='red')
plt.show()
except Exception as e:
print("no good: ",e)
有没有人在这里看到问题?我希望能够处理想要绘制常量函数的用户。清楚的是,当我给它一个像4.0这样的常量时,我希望它向self.y中写入一个列表(它实际上是一维numpy数组,但我们不需要迂腐),长度与self.x相同,填充了4.0的。
这不是一个网络或服务器应用程序,我是非常清楚的固有EVAL的风险(),所以请没有手指晃着如何使用它:)
您可以举一个最简单的例子来描述预期的功能。 – shanmuga