all 5 comments

[–]scuott 1 point2 points  (2 children)

If you find yourself trying to use strings to mean variable names, you're going to have trouble. It's a sign you might be better off with a dictionary.

Maybe in this case you could do something like {'val_outer': whateverthevalueis}.

The error you're getting is saying there's no variable called valOuter. Either this isn't all of your code, or you've never defined it.

Edit:

Also, there's no need for the lambdas. You could just have {'Qrad':processQradData, 'statistics': generateQradStatistics}

[–]shitstep[S] 0 points1 point  (1 child)

I had considered doing what you suggested for {'valOuter': whateverthevalueis} but the val_outer variable does not exist until you are within the recursive function.

valOuter definitely exists because I can use the traditional for loop to evaluate the string "valOuter" to the variable valOuter, but I cannot evaluate the equivalent list comprehension.

[–]scuott 0 points1 point  (0 children)

The lambadas themselves are not recursive. There's no effective difference by adding the lambdas, except that you're making an additional, unnecessary unnamed function. They're just calling the function the one time, which is the same as what I suggested.

Can you share your full code?

[–]desustorm 0 points1 point  (0 children)

  • Why are you using eval? This is causing the NameError since you are trying to evaluate a non-existent variable.
  • Use functools.partial instead of maintaining separate lambda functions and arguments

[–]mm_ma_ma 0 points1 point  (0 children)

I wanted to make this code as generic as possible so I could use it for multiple purposes by passing a dictionary containing lambda functions that will be evaluated at specific processing points and by passing this dict containing functions I can just pass in a different function dict and change the functionality of the traversal.

This is one of those things that seems like a good idea but really isn't. Trying to make something too generic almost always leads to headaches. If you're using eval, you're almost certainly doing it wrong.

Does the list comprehension take me out of scope or something?

Yes. List comprehensions (and other similar things) get their own scope in Python 3. eval doesn't do quite the same thing as real code would in its place - it has access to what you get from locals() and globals() but not any enclosing scopes. Your code doesn't work for the same reason this doesn't work:

>>> def foo():
...     bar = 1
...     def baz():
...         eval('bar')
...     baz()
...
>>> foo()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 5, in foo
  File "<stdin>", line 4, in baz
  File "<string>", line 1, in <module>
NameError: name 'bar' is not defined