3

I need to assign some variables when calling a funcion with the name of the variable as an argument.

Therefore, I loop through a tuple with the desired names, assigning them via the locals() dict.

It works, but then I can't access them by name - even inside the function itself.

def function():
    var_names = ("foo","bar","foobar")
    for var_name in var_names:
        locals()[var_name] = len(var_name)
    print foo

Throws:

Traceback (most recent call last):
  File "error_test.py", line 8, in <module>
    function()
  File "error_test.py", line 5, in function
    print foo
NameError: global name 'foo' is not defined

With the following code it works well:

def function():
    var_names = ("foo","bar","foobar")
    for var_name in var_names:
        locals()[var_name] = len(var_name)
    print locals()["foo"]

Isn't it that the locals() dict contains just the normal function variables? Why isn't it working?

Charles Duffy
  • 280,126
  • 43
  • 390
  • 441
lembon
  • 125
  • 7

2 Answers2

1

When you write:

for var_name in var_names:
    locals()[var_name] = len(var_name)

You modify the locals() dictionary:

as @user2357112 aptly linked in the docs:

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.

So modifying locals() deletes the local variables, hence the NameError: global name 'foo' is not defined error.

Community
  • 1
  • 1
Caridorc
  • 6,222
  • 2
  • 31
  • 46
1

Quoting this post, the explanation seems to be that inside the function you're only retrieving a copy of the namespace and not the namespace itself:

locals does not actually return the local namespace, it returns a copy. So changing it does nothing to the value of the variables in the local namespace.

I'm still looking for a way to change that namespace inside a function, so I'd love to see someone answer this question with a better solution than this.

Ulf Aslak
  • 7,876
  • 4
  • 34
  • 56