# A new syntax for getting the ast node of an expression instead of the value

**URL:** <https://discuss.python.org/t/a-new-syntax-for-getting-the-ast-node-of-an-expression-instead-of-the-value/15338>\
**Category:** Ideas\
**Created:** [April 27, 2022, 6:15pm UTC](https://discuss.python.org/t/a-new-syntax-for-getting-the-ast-node-of-an-expression-instead-of-the-value/15338 "2022-04-27T18:15:45Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![\_builtin.self](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/_builtin.self/32/31874_2.png) [@\_builtin.self](https://discuss.python.org/u/_builtin.self)\
**Post date:** [April 27, 2022, 6:15pm UTC](https://discuss.python.org/t/a-new-syntax-for-getting-the-ast-node-of-an-expression-instead-of-the-value/15338/1 "2022-04-27T18:15:45Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![davidfstr](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/davidfstr/32/6944_2.png) [@davidfstr](https://discuss.python.org/u/davidfstr)\
**Post date:** [April 29, 2022, 1:48pm UTC](https://discuss.python.org/t/a-new-syntax-for-getting-the-ast-node-of-an-expression-instead-of-the-value/15338/2 "2022-04-29T13:48:19Z")

</div>

This kind of syntax sounds similar to defining a Lisp-style Macro in Python.

There is a (stalled) PEP for doing that:

- [PEP 638 – Syntactic Macros](https://peps.python.org/pep-0638/)
- [Related discussion thread](https://mail.python.org/archives/list/python-dev@python.org/thread/U4C4XHNRC4SHS3TPZWCTY4SN4QU3TT6V/)

---

<div class="post-metadata">

**Author:** ![15r10nk](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/15r10nk/32/12183_2.png) [@15r10nk](https://discuss.python.org/u/15r10nk)\
**Post date:** [September 4, 2022, 7:22am UTC](https://discuss.python.org/t/a-new-syntax-for-getting-the-ast-node-of-an-expression-instead-of-the-value/15338/3 "2022-09-04T07:22:12Z")

</div>

You can use [executing](https://github.com/alexmojaki/executing) to get the same result.  
You only have to wrap your expression inside a `lambda` to prevent it to be executed.

script:

```python
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:

```python
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.
