Je travaille sur une application qui permet à un utilisateur de définir une fonction mathématique en entrant une chaîne de caractères (comme vous le voyez sur wolfram alpha) et en traçant la fonction sur plage définie. J'utilise la fonction eval() pour interpréter la chaîne et remplir une liste de valeurs y (liste de valeurs x déjà définies). Je n'autorise l'accès à eval() qu'à quelques fonctions mathématiques numpy et au nom de variable 'x'.Python3: eval() avec un dict personnalisé n'évaluant pas les nombres
Cette classe me permet de créer un objet pour chaque chaîne entrée par l'utilisateur et de créer deux listes, x et y, pour tracer avec matplotlib. Vous pouvez exécuter ce MWE et voir qu'il gère les fonctions de x fin (par exemple, sin (x), ln (x), 3 * x, etc.) et lance des exceptions pour les fonctions non mathématiques comme 'foo' comme souhaité. Cependant, en lui donnant un nombre comme '3' ou '4,00', eval() n'écrit rien dans la liste self.y. Vous pouvez imprimer la forme de self.y à différents points dans le code et vous voyez que dès que eval() s'exécute (quand la chaîne entrée est un nombre) la forme de self.y devient().
#!/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)
Quelqu'un voit-il le problème ici? Je voudrais être capable de gérer l'utilisateur voulant tracer une fonction constante. Pour être clair, quand je lui donne une constante comme 4.0 je veux qu'il écrive une liste dans self.y (c'est en fait un tableau 1D numpy mais nous n'avons pas besoin d'être pédant) de la même longueur que self.x rempli de 4.0 .
Ce n'est pas pour une application Web ou un serveur, je suis parfaitement conscient des risques inhérents à eval() alors s'il vous plaît aucun doigt waggling à l'utiliser :)
Pourriez-vous donner un exemple minimal pour décrire la fonctionnalité prévue. – shanmuga