Auto-Generative Expression Trees for Fun and Profit

Stellt hier eure Projekte vor.
Internetseiten, Skripte, und alles andere bzgl. Python.
Antworten
Benutzeravatar
pillmuncher
User
Beiträge: 1484
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

Jetzt neu mit Monaden! :)

Übers Wochenende hab ich das hier gebaut: http://www.python-forum.de/pastebin.php?mode=view&s=397
Es benötigt codegen, welches es hier gibt: https://pypi.python.org/pypi/codegen/1.0

Sowas kann man damit machen:

Code: Alles auswählen

def test(a, b):
    return a * b

def foo(formula):
    x, y, z = 3, 4, 11
    return expr_eval(formula, globals(), locals())

def bar(formula):
    x, y, z = 'hey', 'ho', 4
    return expr_eval(formula, globals(), locals())

def main():
    x = Name('x')
    y = Name('y')
    z = Name('z')
    test = Name('test')
    exprs = (
        x + test(y, z),
        test(x, z) + y,
    )
    for expr in exprs:
        print('------------------------------')
        print(expr)
        print()
        print('foo:', foo(expr))
        print('bar:', bar(expr))
        print()
        print(repr(expr))
        print()

if __name__ == '__main__':
    main()
Ergebnis:

Code: Alles auswählen

------------------------------
x + test(y, z)

foo: 47
bar: heyhohohoho

BinOp(left=Name(id='x', ctx=Load()), op=Add(), right=Call(func=Name(id='test', ctx=Load()), args=[Name(id='y', ctx=Load()), Name(id='z', ctx=Load())], keywords=[], starargs=None, kwargs=None))

------------------------------
test(x, z) + y

foo: 37
bar: heyheyheyheyho

BinOp(left=Call(func=Name(id='test', ctx=Load()), args=[Name(id='x', ctx=Load()), Name(id='z', ctx=Load())], keywords=[], starargs=None, kwargs=None), op=Add(), right=Name(id='y', ctx=Load()))
Natürlich könnte man in dem Beispiel oben auch einfach einen String an foo() und bar() übergeben. Den syntaktisch korrekt dynamisch zu erzeugen dürfte allerdings nicht so einfach sein. Außerdem hat man, wenn man einen AST hat, auch die Möglichkeit, diesen zu transformieren. In der Doku zum ast Modul gibt es AFAIR ein Beispiel, wie man Namens-Lookup in einen dict-Lookup transformieren kann.

Deswegen könnte man sich zB. nicht nur vorstellen, dass foo() und bar() in einem anderen Prozess (und auf einem anderen Rechner) leben, sondern dass man sich einen Interpreter für Expression-Objekte baut, die direkt auf dem AST operieren. Man könnte dann etwa sowas wie LINQ damit bauen, oder, was mein Einsatzzweck dafür sein wird, eine EDSL für Logikprogrammierung.

Es ist weder fertig, noch gibt es irgendwelche Dokumentation. Wenn man Closures und Dekoratoren versteht (und evtl. Monaden), und die Art und Weise, wie der Attribut-Lookup in Python funktioniert, dann sollte der Code gut zu verstehen sein. Falls nicht, bitte Laut geben, ich erkläre es gerne.

Es funktioniert übrigens erst ab Python 3.2.
In specifications, Murphy's Law supersedes Ohm's.
Antworten