-2

I have some code like this:

def f():
    i = 5
    g(locals())
    print 'in f:', i, j

def g(env):
    env['j'] = env['i'] + 1
    print 'in g:', env['i'], env['j']

f()

I get:

in g: 5 6
in f: 5---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
NameError: global name 'j' is not defined

It seems that g cannot change the local variables got by locals() in f. Is there anyway to change the local variables in other function?

maple
  • 1,828
  • 2
  • 19
  • 28
  • 1
    The answer is to not use `locals()`. What are you actually trying to accomplish? – TigerhawkT3 Aug 15 '16 at 02:35
  • 1
    No, the error points to the local variable `j` that is being accessed in the function `f()`. – Abhishek Balaji R Aug 15 '16 at 02:38
  • @TigerhawkT3 Do you mean that this is not a common requirement in python? – maple Aug 15 '16 at 02:38
  • As says in the [docs](https://docs.python.org/3/library/functions.html#locals): "The contents of this dictionary should not be modified." – Jose Raul Barreras Aug 15 '16 at 02:39
  • @JoseRaulBarreras However, the exec statement can change the local variable in a function, how can it do that? – maple Aug 15 '16 at 02:47
  • 1
    That's correct; this is not a common requirement. I've never seen or heard of anyone actually using `locals()` (or `globals()`) for an appropriate purpose. `exec()` (and `eval()`) are similarly more dangerous than they are practical. – TigerhawkT3 Aug 15 '16 at 02:54
  • @TigerhawkT3 Do you know how exec can do this? Because it changes the variables in other function. – maple Aug 15 '16 at 03:02
  • @maple -- been using python for six years now. Never had a reason to change the python internals -- I dont know what you trying to do.. But gut tells one of two things- either you are doing something wrong or you should not be using python for what you trying to do. Or maybe you should read the source code of python. --- – Merlin Aug 15 '16 at 03:33
  • `g` *can* change the local variables of the calling function. The problem here is that Python, during byte-compilation, thinks that `j` is a global variable. But even if you trick Python (e.g. by writing `j = None` before the call to `g`) you won't get the expected behavior because of the `LOAD_FAST` optimization – Andrea Corbellini Aug 15 '16 at 04:22

1 Answers1

3

According to the docs regarding 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.

An alternative solution is to just return j.

def f():
    i = 5
    j = g(locals())
    print 'in f:', i, j

def g(env):
    j = env['i'] + 1
    print 'in g:', env['i'], j
    return j

f()
Karin
  • 8,404
  • 25
  • 34