Ü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()
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()))
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.