Frage

Angenommen, ich brauche meine eigene kleine DSL zu schaffen, die Python verwenden würde eine bestimmte Datenstruktur zu beschreiben. Z.B. Ich möchte etwas schreiben können, wie

f(x) = some_stuff(a,b,c)

und Python haben, statt klagen über nicht deklarierte Identifikatoren oder versuchen, die Funktion some_stuff aufzurufen, wandeln es in eine wörtliche Ausdruck für meine weiteren Komfort.

Es ist möglich, eine vernünftige Annäherung an diese zu erhalten, indem eine Klasse mit richtig neu definierten __getattr__ und __setattr__ Methoden erstellen und verwenden Sie wie folgt vor:

e = Expression()
e.f[e.x] = e.some_stuff(e.a, e.b, e.c)

Es wäre cool, obwohl sein, wenn es möglich wäre, die lästigen loszuwerden „e.“ Präfixe und vielleicht sogar die Verwendung von [] vermeiden. Also ich frage mich, ist es möglich, vorübergehend „neu zu definieren“ globale Namenssuchen und Zuweisungen irgendwie? Über einen entsprechenden Hinweis, vielleicht gibt es gute Pakete für leicht zu erreichen solche „unter dem Stichwort“ Funktionalität für Python-Ausdrücke?

War es hilfreich?

Lösung

Ich bin nicht sicher, ob es eine gute Idee, aber ich dachte, ich würde es zu versuchen . Fassen wir zusammen:

class PermissiveDict(dict):
    default = None

    def __getitem__(self, item):
        try:
            return dict.__getitem__(self, item)
        except KeyError:
            return self.default

def exec_with_default(code, default=None):
    ns = PermissiveDict()
    ns.default = default
    exec code in ns
    return ns

Andere Tipps

Sie können einen Blick auf dem ast oder parser Module mit Python enthalten nehmen wollen, Zugang zu analysieren und den abstrakten Syntaxbaum (oder Parse-Baum, respectively) des Eingang Code umwandeln. Soweit ich weiß, das Sage mathematische System , in Python geschrieben, hat eine ähnliche Art von Precompilers.

Als Reaktion auf Wai Kommentar, hier ist ein Spaß-Lösung, dass ich gefunden habe. Zunächst einmal zu erklären, einmal mehr, was es tut, nehme an, dass Sie den folgenden Code haben:

definitions = Structure()
definitions.add_definition('f[x]', 'x*2')
definitions.add_definition('f[z]', 'some_function(z)')
definitions.add_definition('g.i', 'some_object[i].method(param=value)')

, wo Definitionen Hinzufügen impliziert die linken Seiten und die rechten Seiten Parsen und andere hässliche Sachen zu tun. Jetzt ein (nicht unbedingt gut, aber sicherlich Spaß) nähern hier erlauben würde, den obigen Code zu schreiben, wie folgt:

@my_dsl
def definitions():
    f[x] = x*2
    f[z] = some_function(z)
    g.i  = some_object[i].method(param=value)

und haben Python tun die meisten der Parsing unter der Haube. Die Idee basiert auf der einfachen exec <code> in <environment> Aussage von Ian erwähnt, mit einer hackish hinaus. Und zwar muss der Bytecode der Funktion leicht gezwickt werden, und alle lokalen Variablen Zugriffsoperationen (LOAD_FAST) geschaltet variablen Zugang von der Umgebung (LOAD_NAME).

Es ist einfacher, gezeigt als erklärt: http://fouryears.eu/wp-content / uploads / pydsl /

Es gibt verschiedene Tricks, die Sie wünschen können, tun es praktikabel zu machen. Zum Beispiel in dem Code auf dem Link oben dargestellten Sie nicht eingebaute Funktionen und Sprachkonstrukte wie für Schleifen und if-Anweisungen innerhalb einer @my_dsl Funktion verwenden können. Sie können diese Arbeit aber machen, um mehr Verhalten der Env-Klasse hinzufügen.

Update . Hier eine etwas ausführlichere Erklärung für die gleiche Sache .

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top