I was wondering if there is a trick to temporarily change the variable scoping rules in Python. For example, is it to possible to temporarily turn the "LEGB" rule into "LB", for debugging purposes?
The reason I'm asking is this: every now and then - especially when running stuff in (larger) ipython notebooks - a typo like the one below, doesn't become a NameError and can result in weird bugs:
def dostuff():
for i in range(3):
print j# typo
j=0
dostuff()
This can partially be addressed with static code checkers, but I thought there might be a neat trick to do this within a function?!
Thanks, Andreas
PS: Yes, polluting namespaces makes the above more likely.
The scoping rules of python are built into the language. You can't change/disable them via any clever tricks that I can think of...
There are a few "best practices" that can help -- particularly when working in scripts. One piece of advice is to pack everything into a main function and call that (which helps with namespace pollution that you mentioned):
def main():
j = 0
dostuff()
if __name__ == '__main__':
main()
But this probably doesn't help you too much when typing things out in the REPL.
EDIT: While you can't change the scoping rules of the language, you can clear out the module's globals, call the function and then reset the globals after the function call. Here's a context manager that demonstrates that sort of usage:
>>> class CopyRestoreDict(object):
... def __init__(self, dct):
... self._dict = dct
... self._copy = {}
... def __enter__(self):
... self._copy.update(self._dict)
... self._dict.clear()
... def __exit__(self, *args):
... self._dict.update(self._copy)
... self._copy.clear()
...
>>> def foo():
... print j
...
>>> j = 1
>>> foo()
1
>>> with CopyRestoreDict(globals()):
... foo()
...
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
NameError: name 'foo' is not defined
>>> j
1
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With