let statement in python



Today, when i wrote another context manager, i came up with the idea – write let statement in python using context manager.

First i invented simple realisation, where we manually pass locals :

from contextlib import contextmanager @ contextmanager def let ( locals_ , ** bindings ): original = { var : locals_ . get ( var ) for var in bindings . keys ()} locals_ . update ( bindings ) yield locals_ . update ( original )

And usage:

>>> a = 1 >>> b = 2 >>> with let ( locals (), a = 10 , b = 20 ): ... print ( a , b ) # inside `let` scope ... ( 10 , 20 ) >>> print ( a , b ) # outside of `let` scope ( 1 , 2 )

Looks ugly. But we can use little piece of magic with inspect . We can get outer frame and get his locals

from contextlib import contextmanager from inspect import currentframe , getouterframes @ contextmanager def let ( ** bindings ): frame = getouterframes ( currentframe (), 2 )[ - 1 ][ 0 ] # 2 because first frame in `contextmanager` decorator locals_ = frame . f_locals original = { var : locals_ . get ( var ) for var in bindings . keys ()} locals_ . update ( bindings ) yield locals_ . update ( original )

Now we don’t need to pass locals explicitly: