Home > front end >  Python lambda and eval scoping within function
Python lambda and eval scoping within function

Time:07-05

I have the following code

def foo(q, s):
    a = 1
    f = lambda x : eval(s)
    return f(1)

foo(1, "x a q")

I would expect the function call to return 3, however I get a NameError instead. I assume that's because eval doesn't have access to the local scope. However I wasn't able to make it work even after passing locals() or a dictionary with the objects.

CodePudding user response:

So, this is clearly documented:

Note, eval() does not have access to the nested scopes (non-locals) in the enclosing environment.

So, you could capture the non-local scope and force eval to use it. How exactly you make this work is up to you and your use-case, here is one example:

>>> def foo(q, s):
...     a = 1
...     nonlocals = locals()
...     def f(x):
...         return eval(s, {**locals(), **nonlocals})
...     return f(1)
...
>>> foo(1, "x a q")
3

Some things to note:

  1. I used the locals() of the function f first. You could switch the order if you want, and it won't matter if and only if there would be no name collisions. Otherwise it is up to you which takes precedence
  2. In the more recent versions of Python, {**locals(), **nonlocals} could be locals() | nonlocals
  3. I didn't use a lambda expression here, to comport with PEP8 style guidelines. Don't assign the result of a lambda expression to a name, that defeats the entire purpose of lambda expressions, which are to be anonymous.
  4. You should consider whether you really need to use eval here. It is likely not the best solution to your problem.
  • Related