Consider the following snippet:
def bar():
return 1
print([bar() for _ in range(5)])
It gives an expected output [1, 1, 1, 1, 1].
However, if I try to exec the same snippet in empty environment (locals and globals both are set to {}), it gives NameError:
if 'bar' in globals() or 'bar' in locals():
del bar
# make sure we reset settings
exec("""
def bar():
return 1
print([bar() for _ in range(5)])
""", {}, {})
NameError: name 'bar' is not defined
If I invoke exec like exec(…, {}) or exec(…), it is executed as expected.
Why?
EDIT:
Consider also the following snippet:
def foo():
def bar():
return 1
print('bar' in globals()) # False
print('bar' in locals()) # True
print(['bar' in locals() for _ in [1]]) # [False]
print([bar() for _ in [1, 2]]) # [1, 1]
Just like in my first exec, we don't have bar in locals inside list comprehension. However, if we try to invoke it, it works!