Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Eval scope in Python 2 vs. 3

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?

like image 297
PattimusPrime Avatar asked Mar 30 '15 00:03

PattimusPrime


People also ask

What are the main differences between python 2 and 3?

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.

How can you tell python 2 from 3?

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.

What does eval () do in python?

Python eval() Function The eval() function evaluates the specified expression, if the expression is a legal Python statement, it will be executed.

What is the use of eval () method in List explain with an example?

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.


1 Answers

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.

like image 98
koukouviou Avatar answered Oct 19 '22 11:10

koukouviou