Eval scope in Python 2 vs. 3 Eval scope in Python 2 vs. 3 python python

Eval scope in Python 2 vs. 3


There is a closed issue in the bug tracker for this: Issue 5242.

The resolution for this bug is won't fix.

Some comments from the Issue read:

This is expected, and won't easily fix. The reason is that list comprehensions in 3.x use a function namespace "under the hood" (in 2.x, they were implemented like a simple for loop). Because inner functions need to know what names to get from what enclosing namespace, the names referenced in eval() can't come from enclosing functions. They must either be locals or globals.

eval() is probably already an hack, there's no need to add another hack to make it work. It's better to just get rid of eval() and find a better way to do what you want to do.


If you want:

def apply_op():    x, y, z = [0.5, 0.25, 0.75]    op = "x,y,z"    return [eval(o) for o in op.split(",")]print(apply_op())

to work you'll need to capture the locals and globals as the issue is that eval(o) is the same has eval(o, globals(), locals()) but as the eval appears within the generator function the results of those functions aren't the same as they were when the eval didn't have a wrapping function so capture them outside the generator and use them inside:

def apply_op():    x, y, z = [0.5, 0.25, 0.75]    op = "x,y,z"    _locals = locals()    _globals = globals()    return [eval(o, _globals, _locals) for o in op.split(",")]print(apply_op())

Or better as x,y,z are locals and the strings are only variable names:

def apply_op():    x, y, z = [0.5, 0.25, 0.75]    op = "x,y,z"    _locals = locals()    return [_locals[o] for o in op.split(",")]print(apply_op())