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
import ast
from uneval import quote, to_ast, to_bytecode
# Build expressions
x, y = quote.x, quote.y # Shortcut for quote("x"), quote("y")
z = x * x + y * y
# 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_bytecode(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}")
Expressions can also be converted to λ-functions:
from uneval import F, quote
x, y = quote.x, quote.y
hello = F("Hello World!")
hello() # => "Hello World!"
plus1 = F.x(x + 1)
plus1(4) # => 5
multiply = F.xy(x * y)
multiply(5, 7) # => 35
Building blocks
from uneval import quote as q
Factory | Example | Result |
---|---|---|
quote |
q('a') or q.a (shortcut) |
a |
if_ |
if_(q.x >= 0, q.x, -q.x) |
x if x >= 0 else -x |
for_ |
for_(q.x**2, (q.x, q.range(5))) |
(x**2 for x in range(5)) |
lambda_ |
lambda_([q.x], q.x * q.x) |
lambda x: x * x |
and_ , or_ |
and_(q.x >= 10, q.x <= 15) |
x >= 10 and x <= 15 |
not_ , in_ |
not_(in_(q.x, {1, 2, 3})) |
not x in {1, 2, 3} |
fstr , fmt |
fstr("sin(", q.a, ") is ", fmt(q.sin(q.a), ".3")) |
f'sin({a}) is {sin(a):.3}' |
Converters
Converter | Target | Remark |
---|---|---|
str |
String | Convert to readable python |
to_ast |
AST-node | Convert to AST-node |
to_bytecode |
Code-object | Compile the expression |
F.parameters |
Function | Create a λ-function |
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 - Unofficial documentation of AST nodes.
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.