The issue with your code is not with map
, but with the list comprehension you're using to consume the map iterator. A list comprehension creates a function behind the scenes, and uses it to produce the list. However, the anonymous function has its own namespace, and its that namespace that eval
is trying to use. That fails, since x
, y
and z
are defined only in the test
namespace, and not in the inner function's namespace.
There are a few ways around the issue. You could pass namespaces to eval
explicitly, as other answers have suggested. Or you could make the function used by the list comprehension close over the variables you care about, with code like this:
def test():
x, y, z = 1, 2, 3
names = 'x', 'y', 'z'
values = map(eval, names)
print( [(x, y, z, str(v)) for v in values] ) # anonymous function will be a closure
But by far the best approach is probably to avoid using eval
in the first place. It's very precarious to use, and if you're passing it data you can't absolutely trust, it's a massive security risk (since eval
will run arbitrary code as long as you can structure it as an expression). For simple expressions like variable names, using dictionary lookups is much better:
def test():
data = {'x': 1, 'y': 2, 'z': 3} # use a dictionary, rather than separate variables
names = 'x', 'y', 'z'
print([str(data[name]) for name in names]) # either do lookups directly
values = map(data.get, names) # or via map
print([str(v) for v in values])