Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

scope of eval function in python

Tags:

Consider the following example:

i=7
j=8
k=10
def test():
    i=1
    j=2
    k=3
    return dict((name,eval(name)) for name in ['i','j','k'])

It returns:

>>> test()
{'i': 7, 'k': 10, 'j': 8}

Why eval does not take into consideration the variables defined inside the function? From the documentation, optionally you can pass a globals and a locals dictionary. What does it means?Finally, how can I modify this small case to make it work?

like image 783
Pierpaolo Avatar asked Dec 09 '14 12:12

Pierpaolo


People also ask

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 () function give example?

What is eval () in python and what is its syntax? 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.

Why do we use eval?

The eval function parses the expression argument and evaluates it as a python expression. In other words, we can say that this function parses the expression passed to it and runs python expression(code) within the program.

What is the difference between eval () and INT () function?

eval evaluates any python code. int tries to convert any type to integer (float, bool, string ...). you got it.

What is eval () function in Python?

Python eval () function parse the expression argument and evaluate it as a python expression and runs python expression (code) within the program. globals (optional): a dictionary to specify the available global methods and variables.

What is the local scope in a Python program?

The local scope in a python program is defined for a block of code such as function. Each function in a python program has its own local scope in which all its variables and object names are defined. The local scope of a function is loaded when the function is called by any other function.

What is the difference between Exec () and Eval () in Python?

The main difference between eval () and exec () is that eval () can only execute or evaluate expressions, whereas exec () can execute any piece of Python code. The first argument to eval () is called expression. It’s a required argument that holds the string-based or compiled-code-based input to the function.

What is global scope in Python with example?

Global Scope. A variable created in the main body of the Python code is a global variable and belongs to the global scope. Global variables are available from within any scope, global and local. Example. A variable created outside of a function is global and can be used by anyone: x = 300. def myfunc ():


2 Answers

Generators are implemented as function scopes:

The scope of names defined in a class block is limited to the class block; it does not extend to the code blocks of methods – this includes generator expressions since they are implemented using a function scope.

So, the generator inside the dict() constructor has its own locals() dictionary. Now let's take a look at Py_eval's source code, specially when both globals() and locals() are None:

if (globals == Py_None) {
        globals = PyEval_GetGlobals();
        if (locals == Py_None)
            locals = PyEval_GetLocals();
    }

So, for your example PyEval_GetLocals() will be empty at the moment the loop is executing and globals() will be the global dictionary. Note that i, j and k defined inside the function are not in local scope of generator, rather they are in its enclosing scope:

>>> dict((name,eval(name, globals(), {})) for name in ['i', 'j', 'k'])
{'i': 7, 'k': 10, 'j': 8}
like image 124
Ashwini Chaudhary Avatar answered Sep 22 '22 15:09

Ashwini Chaudhary


This occurs because the generator expression has a different scope to the function:

>>> def test():
    i, j, k = range(1, 4)
    return dict((j, locals()) for _ in range(i))

>>> test()
{2: {'.0': <listiterator object at 0x02F50A10>, 'j': 2, '_': 0}}

Using j inside the scope binds it from the function, as that's the nearest enclosing scope, but i and k are not locally bound (as k isn't referenced and i is only used to create the range).


Note that you can avoid this issue with:

return dict(i=i, j=j, k=k)

or a dictionary literal:

return {'i': i, 'j': j, 'k': k}
like image 41
jonrsharpe Avatar answered Sep 24 '22 15:09

jonrsharpe