eval() in schleifen

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.
BlackJack

Samstag 27. Dezember 2008, 18:53

@HerrHagen: Es geht nicht nur um "böse" Eingaben, sondern auch um Fehlerhafte, bei denen dem Benutzer unverständliche Fehlermeldungen um die Ohren gehauen werden, sofern er nicht gerade Python kann und nicht nur die Untermenge, die für einen Funktionenplotter interessant ist.

Eine Schnittstelle mit `cmd` und `shlex` wäre IMHO einfach sauberer als den kompletten Pythoninterpreter interaktiv zur Verfügung zu stellen. Was Du machst ist einfach nur Bequemlichkeit und nicht irgendwelche tollen Möglichkeiten nutzen, die ohne `eval()` nicht drin wären.
Benutzeravatar
HerrHagen
User
Beiträge: 430
Registriert: Freitag 6. Juni 2008, 19:07

Samstag 27. Dezember 2008, 19:48

@lunar: Wenn du dir mal das urspüngliche Programm anschaust, wirst du festellen, dass es darum ging schöne bunte Bilder von Funktionen zu erzeugen. Das man statt 2x nun 2*x schreiben muss, spielte dabei glaube ich nur eine untergeordnete Rolle.
Angenommen du willst unbedingt nun unbedingt ein Programm haben was 2x auswertet, musst du natürlich einen entsprechenden Parser schreiben.
Selbst dann gibt es aber noch eine Klasse Anwendung für eval. Du musst ja das geparste Stück Code irgendwie für alle 400x400Pixel ausführen. Das wäre normal verdammt langsam und ein einsatz von Fremdbibliotheken wie numpy wäre auf das codestück nicht so einfach möglich. Du könntest aber auch die Benutzereingabe erst parsen und daraus Python-Syntax erstellen. Damit lässt sich dann mit

Code: Alles auswählen

func = eval("lambda x: x**")
dynamisch eine Funktion erzeugen:
ACHTUNG nicht verwechseln mit:

Code: Alles auswählen

y = eval("x**")
Dann kannst du auch so etwas wie numpy.fromfunction oder die numerischen Integrationsmethoden von scipy und und und,.... nutzen ohne(!) irgendwelchen interface code zu erzeugen. Du hast ja eine ganz normale Python-Funktion erzeugt und nicht irgendeine Datenstruktur die nur dein Programm versteht. Ich hoffe das ist sinnvolle Anwendung genug. Ich warte auf Gegenbeispiele.

@BlackJack: Ich finde: weniger (einfacher) Code, weniger Fehler. Ich bin der Meinung bei Programmierung gehts ja grad um (gesunde) Bequemlichkeit. Ich hoffe dich überzeugt das kombinierte "Parsing dann eval" Beispiel von dem ich oben geschrieben hat.

MFG HerrHagen
Leonidas
Administrator
Beiträge: 16024
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Samstag 27. Dezember 2008, 20:22

HerrHagen hat geschrieben:Dann kannst du auch so etwas wie numpy.fromfunction oder die numerischen Integrationsmethoden von scipy und und und,.... nutzen ohne(!) irgendwelchen interface code zu erzeugen. Du hast ja eine ganz normale Python-Funktion erzeugt und nicht irgendeine Datenstruktur die nur dein Programm versteht. Ich hoffe das ist sinnvolle Anwendung genug. Ich warte auf Gegenbeispiele.
Mit ``_ast`` und ``compile()`` bekommst du genaus das gleiche hin und zusätzlich mit dem Vorteil dass du einen Parser für Mathematische Formeln (also etwa ``3(5+ln 2)`` was hinten und vorne kein gültiger Python Quelltext ist) hast der bei Fehler sinnvolle Fehlermeldungen ausgibt, statt zu versuchen das als Python-Code zu interpretieren und dem User bei Fehler irgendwelche für ihn unverständlichen Fehlermeldungen zu geben.
HerrHagen hat geschrieben:Ich finde: weniger (einfacher) Code, weniger Fehler. Ich bin der Meinung bei Programmierung gehts ja grad um (gesunde) Bequemlichkeit. Ich hoffe dich überzeugt das kombinierte "Parsing dann eval" Beispiel von dem ich oben geschrieben hat.
Bequemlichkeit ist das eine aber eine schlechte Lösung wiegt den geringen Arbeitsaufwand nicht auf. Ich kann zum Beispiel auch gar nichts machen, das ist sehr bequem und löst das Problem sogar noch schlechter.
My god, it's full of CARs! | Leonidasvoice vs Modvoice
Benutzeravatar
HerrHagen
User
Beiträge: 430
Registriert: Freitag 6. Juni 2008, 19:07

Samstag 27. Dezember 2008, 21:36

Ich glaub du hast mich falsch verstanden. Mir ist schon klar, dass man (wie auch immer) parsen muss, wenn man eine nicht-python-syntax haben will. Mein vorschlag bezog sich darauf, wie man das Geparste dann in eine python-funktion umwandelt.
Das _ast Modul finde ich einfach fürchterlich kompliziert. Außerdem haben mich ein paar Dinge immer abgeschreckt es zu benutzen. Hier mal ein Ausschnitt aus der Dokumentation (habe unterstrichen was mich stört):
  • New in version 2.5.

    The _ast module helps Python applications to process trees of the Python abstract syntax grammar. The abstract syntax itself might change with each Python release; this module helps to find out programmatically what the current grammar looks like.
Zudem bin ich mir nicht sicher ob das ganze auch mit anderen Implementation von Python funktionieren würde.
Mit eval(lambda) kannst du eine Funktion zur Laufzeit nur mit reinen Python-Sprachmitteln und ohne Abhängigkeit von einem externen Modul erzeugen.
Ich glaube zudem das das Erzeugen eines Python-Strings weit weniger fehleranfällig ist, als das Modifizieren und Erzeugen eines AST-Baumes. Zumal dieser doch eher unübersichtlich ist. Bei einen Python-String sieht man auf einen Blick wenn man sich beim Erzeugen vertan hat. Nochmal: ich beziehe mich auf die Methode mit der man nach dem Parsen aus der damit erzeugten Datenstruktur z.B. eine Funktion erzeugt. Einen String wie "3(5+ln 2)" direkt z.B. durch irgendwelche Ersetzungen in "3*(5+ln(2))" umzuwandeln ist natürlich (zumindest in den umfangreicheren Fällen) Quatsch. Damit hast du natürlich recht.

MFG HerrHagen
Leonidas
Administrator
Beiträge: 16024
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Sonntag 28. Dezember 2008, 02:16

HerrHagen hat geschrieben:
  • New in version 2.5.

    The _ast module helps Python applications to process trees of the Python abstract syntax grammar. The abstract syntax itself might change with each Python release; this module helps to find out programmatically what the current grammar looks like.
Zudem bin ich mir nicht sicher ob das ganze auch mit anderen Implementation von Python funktionieren würde.
Naja, wir können uns auch auf Python 2.2 limitieren, nur wozu? Python 2.5 hat sich nun in fast allen Bereichen durchgesetzt (außer Zope 2) und 2.6 tritt langsam aber stetig die Nachfolge an. Um es doch einmal besser zu formulieren: "Python 2.5 was released on September 19th 2006." Das ist 2 Jahre und 3 Monate her, 27 Monate also. Zeit genug um zu migrieren. Und wenn man nicht will, gibt es noch die lustigen PEAK-Libraries von PJE mit denen man auch verschiedene Dinge basteln kann (ich denke da an Sachen wie BytecodeAssembler etc).

birkenfeld hat ein kleines Beispiel was man mit ``_ast`` so machen kann. An einem Parser kommt man IMHO kaum vorbei, und dann hat man entweder die Möglichkeit selbst einen Interpreter zu schreiben oder eben einen AST zu generieren und es in Python-Code zu wandeln.
My god, it's full of CARs! | Leonidasvoice vs Modvoice
Antworten