eval() in Variable speichern

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Benutzeravatar
classic
User
Beiträge: 23
Registriert: Mittwoch 3. September 2008, 15:37
Wohnort: Erfurt bzw Lauchröden

Hi,

Ich bin für die Schule an einem Projekt, um nichtlineare Gleichungen darzustellen.

Diese soll der Nutzer auch eingeben können.

Also lese ich diesen String der Funktion ein und "interpretiere" ihn mittels der eval-Funktion.
Also um den Funktionswerts eines Punktes zu bekommen:

Code: Alles auswählen

def parse(mystr,x):
    return eval(mystr,{'x':x})
Nun meine Frage:
Ist es möglich, dass ich mir anstatt den String zu speichern, dieses eval() in Abhängigkeit von x speichere (also quasi als "richtige" Funktion von x [f(x)=...]) ?
Oder hat das ständige Evaluieren (für momentan ~ 400 x-Werte) kaum Performance-Einbußen?

MfG
classic
Benutzeravatar
Defnull
User
Beiträge: 778
Registriert: Donnerstag 18. Juni 2009, 22:09
Wohnort: Göttingen
Kontaktdaten:

Nicht mit eval() direkt, aber mit compile() und ein paar Umwegen.

Code: Alles auswählen

>>> namespace = {}
>>> formula = 'x*5'
>>> code = compile('def func(x): return %s' % formula, '<string>', 'exec')
>>> eval(code, namespace)
>>> func = namespace.get('func')
>>> func(5)
25
>>> func(6)
30
Allerdings wird dir kein Lehrer glauben, das du das selbst heraus gefunden hast.

Und noch was für's Leben: eval() und ähnliche Dinge sind böse. Benutze sie nur, wenn du GENAU weist, was du da tust. Für Lern-Zwecke sind sie brauchbar aber in echter Software meistens Fehl am Platze oder sogar gefährlich.

Edit: Blöd das ich da nicht gleich drauf gekommen bin, es geht auch einfacher:

Code: Alles auswählen

>>> formula = 'x*5'
>>> func = eval('lambda x: %s' % formula)
>>> func(4)
20
Bottle: Micro Web Framework + Development Blog
Benutzeravatar
classic
User
Beiträge: 23
Registriert: Mittwoch 3. September 2008, 15:37
Wohnort: Erfurt bzw Lauchröden

Ok, Dankeschön, das mit lambda ist auch nicht so unrealistisch, habe ich selbst auch schon mal verwendet ;)

Aber warum ist eval() gefährlich?
Gibt es denn andere Möglichkeiten Formeln die der Nutzer eingibt zu interpretieren?
Man kann den String ja sicherlich auch so parsen, aber das ist wahrscheinlich ein relativ großer Aufwand, würde sich das denn so signifikant lohnen?

MfG
classic

Edit:
Noch eine Frage:
Wenn der Nutzer nun beispielsweise eine Sinuskurve will, dann muss er Math.sin(x) eingeben [Falls ich im globals-Dictionary 'math':math stehen habe], damit es klappt.
Ist es möglich, dass er nur sin(x) eingeben muss?
BlackJack

@classic: `eval()` ist gefährlich weil der Benutzer da beliebige Ausdrücke eingeben kann. Wenn Du dem Benutzer zum Beispiel erlaubst die Formeln auch in eine Datei zu speichern, um sie später wiederzuverwenden, könnte jemand auf die Idee kommen da "böse" Sachen zu speichern, wie zum Beispiel das Löschen aller Dateien im Heimatverzeichnis, und diese Datei dann versuchen anderen Benutzern des Programms unterzuschieben.

Zur zweiten Frage: Du musst in das Dictionary halt einfach alle Attribute vom `math`-Modul übertragen. Schau Dir mal `dir()` und `getattr()` an. Altenativ `inspect.getmembers()`.
Benutzeravatar
classic
User
Beiträge: 23
Registriert: Mittwoch 3. September 2008, 15:37
Wohnort: Erfurt bzw Lauchröden

Ok, aber ich glaube bei unserem Schülerprojekt spielt das keine so große Rolle :P

Danke, das mit dir() und getattr() hat funktioniert ;)

MfG
classic
ms4py
User
Beiträge: 1178
Registriert: Montag 19. Januar 2009, 09:37

Alternativ kannst du dir mal meinen Funktionsparser anschauen.
Code: http://bitbucket.org/ms4py/sitforc/src/ ... cparser.py
Kurze Erklärung: http://bitbucket.org/ms4py/sitforc/down ... parser.pdf
„Lieber von den Richtigen kritisiert als von den Falschen gelobt werden.“
Gerhard Kocher

http://ms4py.org/
Benutzeravatar
HerrHagen
User
Beiträge: 430
Registriert: Freitag 6. Juni 2008, 19:07

Vielleicht ist sympy auch für dich interessant:
http://docs.sympy.org/tutorial.html
Damit kannst du auch symbolisch rechnen. Also sowas hier:

Code: Alles auswählen

>>> x+y+x-y
2*x
>>> diff(sin(2*x), x)
2*cos(2*x)
Antworten