The f_locals
of a module stack frame are its globals()
!
You can verify this by printing the is
comparison with globals()
inside the modify
function:
def modify():
print(inspect.stack()[1][0].f_locals is globals())
inspect.stack()[1][0].f_locals['a'] = 8888
With this change the output is:
$python3 modify.py
10
False
10
20
True
8888
Modifying the dictionary returned by globals()
does work (see this question). It is explicitly documented that modules implement their namespace with a simple dict
:
Modules are imported by the import
statement (see section The import
statement). A module object has a namespace implemented by a
dictionary object (this is the dictionary referenced by the
func_globals
attribute of functions defined in the module).
However the dictionary returned by locals()
does not have to be the local namespace:
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.
In some versions of python2 modifying locals()
works when using the exec
statement inside the function. Try to add exec ''
inside the outer
function and see whether the output changes (it isn't guaranteed to change! However it is more likely).
Edit: On python 2.7.6 I can make it work if the stack frame uses the exec
statement and there is no assignment to a local variable in the code. For example with outer
defined as:
def outer():
exec('a = 10')
print(a)
modify()
print(a)
locals()['a'] = 9999
print(a)
I get the output:
$python2 modify.py
10
False
8888
9999
20
True
8888
But if I add a = 10
after the exec
as in:
def outer():
exec('a = 10')
a = 10
print(a)
modify()
print(a)
locals()['a'] = 9999
print(a)
The result is:
$python2 modify.py
10
False
10
10
20
True
8888
I hope this shows you that the conditions in which assigning to locals work are really few and absolutely not reliable.
AFAIK in python3 the dictionary returned by locals()
is always just a copy of the real namespace, so modifying it never works. However there is no guarantee either.
The value returned by the f_locals
attribute is simply the value returned by locals()
at that point.
In summary: no, there is no reliable way to modify the local namespace of a generic stack frame. You cannot modify, delete nor add new local variables to a generic stack frame's namespace.