Consider the following snippet:
def bar():
return 1
print([bar() for _ in range(5)])
It gives an expected output [1, 1, 1, 1, 1]<
Edit
To answer your edited question, user @Hendrik Makait said bar is not in the scope of list comprehension:
def foo():
def bar():
return 1
print('bar' in globals()) # False, because the scope of foo and bar are diferents, foo is globals() scope, bar are in the scope of foo
print('bar' in locals()) # True
print(['bar' in locals() for _ in [1]]) # [False], because a new implicit scope is defined in list comprehension, as user @Antti Haapala said
print([bar() for _ in [1, 2]]) # [1, 1]
To answer the original question:
If you create two different dictionaries, it wont recognize the local and globals definitions, the variables are not updated as @PM 2Ring said:
exec("""
def bar():
return 1
print(bar())
print("bar" in globals())
print("bar" in locals())
print([bar() for _ in range(5)])
""", {},{})
it prints:
1
False #not in globals
True
Traceback (most recent call last):
File "python", line 17, in
File "", line 7, in
File "", line 7, in
NameError: name 'bar' is not defined
A way to do it, is update the variables, like this globals().update(locals()):
exec("""
def bar():
return 1
globals().update(locals())
print("bar" in globals())
print("bar" in locals())
print([bar() for _ in range(5)])
""", {}, {})
wich gives:
True
True
[1, 1, 1, 1, 1]
But, if you remove the dictionaries, or create one and give it to the exec function as same parameter, it works:
d={}
exec("""
def bar():
return 1
print("bar" in globals())
print("bar" in locals())
print([bar() for _ in range(5)])
""",d,d)
it prints:
True
True
[1, 1, 1, 1, 1]
That's why you get the error, it could't find your function in the globals
Or simply, don't give the parameters:
exec("""
def bar():
return 1
print(bar())
print("bar" in globals())
print("bar" in locals())
print([bar() for _ in range(5)])
""")
Cause the same efect.