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` is the decorator
locals_ = frame.f_locals
original = {var: locals_.get(var) for var in bindings.keys()}
locals_.update(bindings)
yield
locals_.update(original)
def f():
x = 1
with let(x=3):
print(x)
f()
print(x)
ZnJvbSBjb250ZXh0bGliIGltcG9ydCBjb250ZXh0bWFuYWdlcgpmcm9tIGluc3BlY3QgaW1wb3J0IGN1cnJlbnRmcmFtZSwgZ2V0b3V0ZXJmcmFtZXMKCkBjb250ZXh0bWFuYWdlcgpkZWYgbGV0KCoqYmluZGluZ3MpOgogICAgZnJhbWUgPSBnZXRvdXRlcmZyYW1lcyhjdXJyZW50ZnJhbWUoKSwgMilbLTFdWzBdICMgMiBiZWNhdXNlIGZpcnN0IGZyYW1lIGluIGBjb250ZXh0bWFuYWdlcmAgaXMgdGhlIGRlY29yYXRvciAgCiAgICBsb2NhbHNfID0gZnJhbWUuZl9sb2NhbHMKICAgIG9yaWdpbmFsID0ge3ZhcjogbG9jYWxzXy5nZXQodmFyKSBmb3IgdmFyIGluIGJpbmRpbmdzLmtleXMoKX0KICAgIGxvY2Fsc18udXBkYXRlKGJpbmRpbmdzKQogICAgeWllbGQKICAgIGxvY2Fsc18udXBkYXRlKG9yaWdpbmFsKQoKZGVmIGYoKToKICAgIHggPSAxCiAgICB3aXRoIGxldCh4PTMpOgogICAgICAgIHByaW50KHgpCgpmKCkKCnByaW50KHgp