I propose a new syntax to get the ast of an expression instead of always being evaluated to allow expressions to be passed to function.
The main syntax for forcing python to return the ast of an expression would be \(expression) where expression is any python expression.
For example \(my_var+2) would be equal to ast.Binop(ast.Name("my_var" , ast.Load() ) , ast.Add , ast.Constant(2))
The main use case would be simplify expressions such thoughts used in boolean indexing. Instead of having to write dataframe[(dataframe.column_1 > 5) & (dataframe.column_2< 10)] you could instead write dataframe[\((column_1 > 5) & (column_2 <10))
It would also make creating an ast transformer simpler and easier by allowing static ast nose to be written in python directly instead of having to create the node directly.
You can use executing to get the same result.
You only have to wrap your expression inside a lambda to prevent it to be executed.
script:
from executing import Source
import inspect
import ast
class DataFrame:
def __getitem__(self, item):
subscript=Source.executing(inspect.currentframe().f_back).node
if isinstance(subscript.slice,ast.Lambda):
lambda_=subscript.slice
else:
# the slice is a ast.Index before python 3.7
lambda_=subscript.slice.value
print("do something with", ast.dump(lambda_.body))
dataframe = DataFrame()
dataframe[lambda:(column_1 > 5) & (column_2 <10)]
output:
do something with BinOp(left=Compare(left=Name(id='column_1', ctx=Load()), ops=[Gt()], comparators=[Num(n=5)]), op=BitAnd(), right=Compare(left=Name(id='column_2', ctx=Load()), ops=[Lt()], comparators=[Num(n=10)]))
python version: Python 3.5.3
The disadvantage is that this breaks the lambda semantics.
The reader (or any other tool like a linter) might expect that column_1 is a local variable and be confused.