我正在研究一個應用程序,它允許用戶通過輸入一個字符串來定義一個數學函數(就像你在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