Ist es möglich, etwas wie
zu tun? %Vor%in Python..i.e. Haben func1 () und func2 () im Rahmen des Objekts 'c' ausgewertet (wenn sie Mitgliedfunktionen innerhalb dieser Klassendefinition waren)? Ich kann kein einfaches Parsing machen, da die eval-Strings für meine Anwendung beliebig kompliziert werden können. Ich denke, ein bisschen Magie mit dem ast-Modul könnte den Trick machen, aber aufgrund der Menge an Literatur in ast, bin ich mir nicht sicher, wo ich hinschauen soll:
%Vor%Sie wollen das fast sicher nicht, aber Sie können .
Der Kontext für eval
ist die globale und lokale Wörterbücher, die Sie Ihren Code auswerten möchten Die häufigsten Fälle sind wahrscheinlich eval(expr, globals(), mycontext)
und eval(expr, mycontext)
, die den lokalen bzw. globalen Standardkontext ersetzen und den anderen in Ruhe lassen. Das Ersetzen des lokalen Kontexts durch das Wörterbuch eines Objekts ähnelt dem Ausführen von "innerhalb" (einer Methode) dieses Objekts. Beachten Sie jedoch, dass "eine Mitgliedsfunktion zu sein" nicht so gut ist, wie Sie vielleicht erwarten würden Haben Sie self
, um andere Memberfunktionen auf ...
Wie auch immer, hier ist ein kurzes Beispiel:
%Vor% Beachten Sie, dass __dict__
hier möglicherweise nicht genau das ist, was Sie wollen. Zum Beispiel:
Damit dies so funktioniert, wie Sie es wollen, müssen Sie genau wissen, wie Sie das wollen, in Python-Begriffen - was ein bisschen darüber wissen muss, wie Objekte unter den Deckeln funktionieren (MRO, vielleicht Deskriptoren, etc.) / p>
Wenn Sie wirklich eval
benötigen und wirklich beliebige Kontexte bereitstellen müssen, ist es wahrscheinlich besser, diese Kontexte explizit (als Wörterbücher) zu erstellen, anstatt zu versuchen, Objekte in diese Rolle zu zwingen:
Diese Verwendung ist viel näher an dem JavaScript-Stil, den Sie in Python trotzdem emulieren möchten.
Im Gegensatz zu JS lässt Python natürlich keine mehrzeiligen Definitionen innerhalb eines Ausdrucks zu, so dass Sie dies für komplexe Fälle tun müssen:
%Vor%Aber das ist wohl fast immer lesbarer (was im Grunde das Argument dafür ist, dass Python keine mehrzeiligen Definitionen in Ausdrücken zulässt).
Also, ich rate dir, so etwas zu tun:
%Vor%Scheint so, als ob Sie brauchen. Lassen Sie mich erklären, wie das funktioniert.
eval
akzeptiert Locals und Globals als Parameter. globals
-Wörterbuch alle "wertvollen" begrenzten Methoden bereitstellen. S
-Klassendefinition. Wie bekommt man alle "wertvollen" Methoden? Simple filter
Namen von S.__dict__
, um zu überprüfen, ob der Methodenname von __
beginnt oder nicht (Sie sehen, dass wir als Ergebnis eine Liste mit 1 Element erhalten - add
function). target
= Instanz von S
class, die "eval context" sein wird. __dict__
Funktionen speichert, jede Funktion ist kein Datendekriptor und die gebundene Methode kann einfach mit func.__get__(obj, type(obj))
abgerufen werden. Dieser Vorgang wird in map
ausgeführt. dict
daraus. globals
an eval
function. Ich hoffe, das wird helfen.
Die oben vorgeschlagene Lösung zum Auffüllen von locals
funktioniert in den meisten Fällen gut, kann aber bei Eigenschaften (Datendeskriptoren) problematisch sein. Diese werden einmal bewertet , wenn das Wörterbuch gefüllt ist. Dies bedeutet, dass mehrere Verweise auf denselben Variablennamen immer die exakt gleiche Instanz zurückgeben, was bei Eigenschaften nicht erwartet werden kann.
Dieses Problem kann dadurch gelöst werden, dass eval
ein locals
Argument erwartet, das sich wie ein dict
verhält (im Gegensatz zu globals, die sein müssen ) ein Code%). Mit anderen Worten, wir können dict
in Ihrer Instanz überschreiben, um Variablennamen im Kontext der Instanz spontan aufzulösen und sie direkt als __getitem__
-Attribut an locals
weiterzuleiten. Ihr Beispiel kann so implementiert werden als:
Dieser Trick sollte mit Vererbung, statischen Methoden, Klassenmethoden und Eigenschaften funktionieren. Schließlich verhindert die Verwendung von eval
und dir
die direkte Interaktion mit getattr
oder __dict__
, obwohl die Ergebnisse von __mro__
möglicherweise .
Sie können sich die akzeptierte Antwort auf diese Frage ansehen: " Abrufen des Befehlsblocks, der in der with-Anweisung ausgeführt werden soll .
Dies war eine hilfreiche Möglichkeit für mich, eigene Kontexte zu erstellen, in denen mathematische Operationen auf rechteckigen Arrays, wie Python Pandas-Datenrahmen, "einfach funktionieren", ohne sich mit der hässlichen zusätzlichen Pandas-Syntax herumschlagen zu müssen. Wenn ich zum Beispiel " a = x*y
" in den Kontext schreibe, weist es dem Kontextobjekt automatisch a
als Attribut zu und weiß, dass Vektoroperationen mit den Attributen x
und y
des Kontextobjekts ausgeführt werden.
Ich habe diesen Kontext als sehr hilfreich empfunden, obwohl ich, wenn ich auf StackOverflow frage, oft die Antwort bekomme, dass es nicht unbedingt das ist, was ich wirklich machen möchte.
Dies könnte wahrscheinlich für den Kontext funktionieren, in dem eval
auch nach Funktionen sucht.
Tags und Links python eval abstract-syntax-tree