I came across bizarre eval behavior in Python 3 - local variables aren't picked up when eval is called in a list comprehension.
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())
It errors in Python 3:
▶ python --version Python 3.4.3 ▶ python eval.py Traceback (most recent call last): File "eval.py", line 7, in <module> print(apply_op()) File "eval.py", line 5, in apply_op return [eval(o) % 1 for o in op.split(",")] File "eval.py", line 5, in <listcomp> return [eval(o) % 1 for o in op.split(",")] File "<string>", line 1, in <module> NameError: name 'x' is not defined
And it works fine in Python 2:
▶ python --version Python 2.7.8 ▶ python eval.py [0.5, 0.25, 0.75]
Moving it outside of the list comprehension removes the problem.
def apply_op(): x, y, z = [0.5, 0.25, 0.75] return [eval("x"), eval("y"), eval("z")]
Is this intended behavior, or is it a bug?
In Python 3, the new Range() function was introduced to perform iterations. Python 2 has more complicated syntax than Python 3. Python 3 has an easier syntax compared to Python 2. A lot of libraries of Python 2 are not forward compatible.
One of the most basic differences between Python 2 and 3 is the print statement. In Python 2, print is a special statement used to print values on the console. This means that parentheses are not needed while invoking the print statement.
Python eval() Function The eval() function evaluates the specified expression, if the expression is a legal Python statement, it will be executed.
Answer: eval is a built-in- function used in python, eval function parses the expression argument and evaluates it as a python expression. In simple words, the eval function evaluates the “String” like a python expression and returns the result as an integer.
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 love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With