Reputation: 393
I'm trying to make a list containing data which has been processed by different functions. The below code does not work, because the two functions a and b are not within the scope of the map function
def outer_func():
def a():
return "Something"
def b():
return "Something else"
map(lambda x: eval(x)(), ['a', 'b'])
I tried wrapping the functions in a class, and the below code works just fine.
class fcontainer():
def a(self):
return "Something"
def b(self):
return "Something else"
def test():
f = fcontainer()
return map(lambda x: getattr(f, x)(), ['a', 'b'])
Now, my questions are:
Thank you!
UPDATE: The first example can be made to work by first fetching the functions while within the scope of outer_func, and then using map:
functions = [eval(i) for i in ['a', 'b']]
return map(lambda x: x(), functions)
This works, but it's two lines instead of one >:|
Upvotes: 0
Views: 433
Reputation: 1896
In python, we have a special feature where you can pass a function just like a variable.
Your first approach is almost correct,.. slightly missed :)
>>> def outer_func():
... def a():
... return "Something"
... def b():
... return "Something else"
... print map(lambda x: x(), [a, b])
...
>>> outer_func()
['Something', 'Something else']
eval is really good but like you faced, it has a risk of
If use this for your second approach, it will work.
>>> def test():
... f = fcontainer()
... return map(lambda x: x(), [f.a, f.b])
...
>>> test()
['Something', 'Something else']
Now, to your questions :
Q1. Why do a and b not exist within the map function?
MAP function is special. It does nt bother what is outside its scope. This makes it much more faster. check below code to understand.
>>> dir() # used to check local variables/function defined already.
['__builtins__', '__doc__', '__name__', '__package__', 'outer_func']
>>> map( lambda x: dir() , range(5))
[['x'], ['x'], ['x'], ['x'], ['x']]
>>> # as you can see within MAP, outer_func is missing.
Q2. Is there a 'right' way to do what I'm trying to do?
There is a easier way to do it :)
Q3. Should I finally sit down and wrap my head around decorators?
I think you already got answer by now. So for now no decorations
Hope this helps you :)
Upvotes: 0
Reputation: 91119
Is it necessary to have a list of strings (['a', 'b']
)? Maybe you'd better put the function objects directly into the list: [a, b]
.
return map(lambda x: x(), [a, b])
seems quite easy to me.
If you want to do it as decorators, it won't be much easier:
def outer_func():
funcs = []
def funcapp(func): # so that a and b are still in place...
funcs.append(func)
return func
@funcapp
def a():
return "Something"
@funcapp
def b():
return "Something else"
return funcs
Upvotes: 4
Reputation: 97641
You need to make sure eval
executes in the right context, by giving it the globals
and locals
inside outer_func()
.
def outer_func():
def a():
return "Something"
def b():
return "Something else"
map(lambda x, g=globals(), l=locals(): eval(x, g, l)(), ['a', 'b'])
Having said that, eval
is probably not the solution to your problem
Upvotes: 1