Library for generating python-expressions
Project description
UnEval
UnEval is a microlibrary for generating python-expressions.
If you ever need to use eval, write macros or implement domain specific languages, this library provides a better way to generate python expressions than using strings. Strings can contain syntax errors, make it harder to deal with parentheses and aren't syntax highlighted. Expressions look and act a lot like pythoncode, except that they aren't evaluated immediately.
Installation
Make sure to install pip then run:
pip install uneval
Usage
Firstly, the building blocks can be used to generate expressions. Secondly, these expressions can be converted.
Examples
# Build expressions
x, y = quote.x, quote.y # Shortcut for quote("x"), quote("y")
z = x*x + y*y
d = z.abs() + x.pow(3) - y.sin(x)
# Convert
print(z) # x * x + y * y
print(ast.dump(to_ast(z))) # BinOp(left=BinOp(left=Name(id='x', ctx=Load()), op=Mult(), right=Name(id='x', ctx=Load())), op=Add(), right=BinOp(left=Name(id='y', ctx=Load()), op=Mult(), right=Name(id='y', ctx=Load())))
print(eval(to_code(z), {"x": 3, "y": 4})) # 25
This can be used when working in pandas and you want to use eval or query:
from uneval import quote as q
# No syntax highlighting. Syntax checkers won't catch errors.
df.eval("bmi = mass / height**2")
# With syntax highlighting. Syntax checkers can catch errors here.
df.eval(f"bmi = {q.mass / q.height**2}")
These blocks can even be used to create alternative syntax for lambda-functions:
from uneval import Expression, to_code, lambda_, quote
x = quote.x
def f_x(expr: Expression):
"""Create a lambda with parameter x."""
return eval(to_code(lambda_([x], expr)))
square = f_x(x * x) # Same as: `lambda x: x * x`
print(square(5)) # => 25
Building blocks
Factory | AST-class | Example | Result |
---|---|---|---|
quote |
ast.Name |
quote('a') or quote.a (shortcut) |
a |
if_ |
ast.IfExpr |
if_(quote.x >= 0, quote.x, -quote.x) |
x if x >= 0 else -x |
for_ |
ast.GenExpr |
for_(quote.x ** 2, (quote.x, quote.range(5))) |
(x**2 for x in range(5)) |
lambda_ |
ast.Lambda |
lambda_([quote.x], quote.x * quote.x) |
lambda x: x * x |
and_ , or_ |
ast.BoolOp |
and_(quote.x >= 10, quote.x <= 15) |
x >= 10 and x <= 15 |
not_ , in_ |
ast.Not(), ast.In() |
not_(in_(quote.x, {1, 2, 3})) |
not x in {1, 2, 3} |
Converters
Converter | Target | Remark |
---|---|---|
str |
String | Convert to readable python |
to_ast |
AST-node | Generate AST-node |
to_code |
Code-object | Compile the expression |
Similar work
Libraries that implement something similar:
- Macropy has quasiquote.
- SymPy - Symbolic manipulation, but its representation is different from Python.
- Polars - Writing
col.x
creates something like thisExpression
-object.
Other:
- Fixing lambda - A blog post about alternative lambda syntaxes.
- Mini-lambda - Packages to "fix" lambda.
- Meta - A few utils to work on AST's.
- latexify - Converts python to LaTeX.
Useful references:
- python macros use cases - Stack-overflow discussion.
- Green tree snakes - Documention about AST.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.