Reputation: 3517
I am trying to create a dictionary with dictionary comprehensions in the following way (which is part of a much larger code)
columns = ['zeta', 'Lm', 'u_mean']
print('zeta', eval('zeta'))
print(locals())
dic = {col: [eval(col)] for col in columns}
The first print
prints exactly as expected (the value of the variable zeta
) and the second print
confirms that zeta
is in the locals dictionary, but in the dictionary comprehension command python fails with this error
NameError: name 'zeta' is not defined
Unfortunately, when trying to reproduce to error in order to post here, I found out that I can't reproduce the error, because the following commands work in ipython
:
zeta,Lm,u_mean=1,4,69
columns=['zeta', 'Lm', 'u_mean']
print('zeta',eval('zeta'))
print(locals())
dic={ col : [eval(col)] for col in columns }
It is only those commands inside my code that do not work. So, am I missing something? Is there some test I can do to see what's wrong?
Upvotes: 4
Views: 560
Reputation: 1123270
A dictionary comprehension is executed in a new scope, a lot like a nested function call. You cannot expect to access the locals of the parent scope in a list comprehension.
I strongly recommend you do not use locals like this. Create a separate dictionary to act as a namespace and look up your columns in that:
namespace = {
'zeta': value_for_zeta,
# ... etc.
}
then use {col: [namespace[col]] for col in columns}
.
Failing that, you can store the locals()
dictionary in a new variable and reference that; either directly, or through passing it in as the namespace for eval()
:
namespace = locals()
dic = {col: [eval(col, namespace)] for col in columns}
or simply:
namespace = locals()
dic = {col: [namespace[col]] for col in columns}
This works now because namespace
is a closure; a name taken from the parent scope.
Note that the same limits apply to generator expressions, set comprehensions, and in Python 3, list comprehensions. Python 2 list comprehensions were implemented before all the other types and followed a different implementation strategy that did not involve a new scope, but this approach did not allow for generator expressions to work and the new approach with a separate scope was generally found to work better.
Upvotes: 6