Setting variables with exec inside a function
You're almost there. You're trying to modify a global variable so you have to add the global
statement:
old_string = "didn't work"
new_string = "worked"
def function():
exec("global old_string; old_string = new_string")
print(old_string)
function()
If you run the following version, you'll see what happened in your version:old_string = "didn't work"
new_string = "worked"
def function():
_locals = locals()
exec("old_string = new_string", globals(), _locals)
print(old_string)
print(_locals)
function()
output:didn't work
{'old_string': 'worked'}
The way you ran it, you ended up trying to modify the function's local variables in exec
, which is basically undefined behavior. See the warning in the exec
docs:and the related warning onNote: The default locals act as described for function
locals()
below: modifications to the default locals dictionary should not be attempted. Pass an explicit locals dictionary if you need to see effects of the code on locals after functionexec()
returns.
locals()
:Note: The contents of this dictionary should not be modified; changes may not affect the values of local and free variables used by the interpreter.
How pass a value to a variable in python function with using exec()?
Python knows several kinds of scope: module global
, function local, nonlocal
closures, class body. Notably, scope resolution is defined statically at byte code compile time – most importantly, whether names refer to local/nonlocal or global scope cannot be changed.
Of these scopes, only global scope is guaranteed to behave similar to a dict
, and as such writeable. The local/nonlocal scope is generally not writeable, and new variables cannot be added to it.
exec
will write to the global scope if locals is not passed in; globals must then explicitly be set to its default of globals()
.
def func():
exec("a='exec'", globals()) # access only global scope
print(a)
a = 'global'
func() # prints exec
However, once a name is local to a function, exec
cannot modify it.def func():
a = 'local' # assignment makes name local
exec("a='exec global'", globals())
exec("a='exec locals'", globals(), locals())
print(a)
a = 'global'
func() # prints local
While a
dict
-like representation of local/nonlocal scope exists, the interpreter is not required to honour changes to it.Even thoughlocals()
Update and return a dictionary representing the current local symbol table. Free variables are returned by locals() when it is called in function blocks, but not in class blocks. Note that at the module level, locals() and globals() are the same dictionary.Note: The contents of this dictionary should not be modified; changes may not affect the values of local and free variables used by the interpreter.
exec
does take locals as a dict
, these are not treated like function locals/nonlocals. Attempts to modify the default locals (the result of locals()
) are not defined.exec()
... If globals and locals are given, they are used for the global and local variables, respectively. If provided, locals can be any mapping object. Remember that at module level, globals and locals are the same dictionary. If exec gets two separate objects as globals and locals, the code will be executed as if it were embedded in a class definition.Note: The default locals act as described for functionlocals()
below: modifications to the default locals dictionary should not be attempted. ...
Running exec inside function
It's going to damage your function's performance, as well as its maintainability, but if you really want to make your own code so much worse, Python2 (this will not work in Python3, there you need to use the second alternative) gives you "enough rope to shoot yourself in the foot" (;-):
>>> def horror():
... exec "x=23"
... return x
...
>>> print horror()
23
A tad less horrible, of course, would be to exec
in a specific dict:>>> def better():
... d = {}
... exec "x=23" in d
... return d['x']
...
>>> print better()
23
This at least avoids the namespace-pollution of the first approach. assignment within exec in python
global x = 5
is not valid python code.If you want to assign to a global variable x
, you should write
global x
x = 5
Try changing your code asglobal x
eqn1 = "{0} = {1}".format("x",eqn)
x = 0
exec(eqn1, globals())
To modify global variables with exec, you need to use globals() function.EDIT: Add globals() function.
Use exec to modify global variables in a class
exec()
has optional arguments for you to provide the global and local variable contexts.
But you didn't provide them.
Related Topics
Most Efficient Way to Reverse a Numpy Array
Differencebetween Np.Array() and Np.Asarray()
"Pip Install --Editable ./" VS "Python Setup.Py Develop"
Python Pip on Windows - Command 'Cl.Exe' Failed
Nan Loss When Training Regression Network
Numpy Array Initialization (Fill with Identical Values)
Python Memory Usage of Numpy Arrays
Django/Python Beginner: Error When Executing Python Manage.Py Syncdb - Psycopg2 Not Found
How to Create Module-Wide Variables in Python
How to Reverse a Dictionary That Has Repeated Values
Failed Loading English.Pickle with Nltk.Data.Load
Start a Flask Application in Separate Thread
How to Use Python-Docx to Replace Text in a Word Document and Save
How to Find the Min/Max Value of a Common Key in a List of Dicts