Python vars () global name error

I am having trouble understanding what is happening with the following function:

def ness(): pie='yum' vars()[pie]=4 print vars()[pie] print yum 

So, when I run, I get this result:

 >>> ness() 4 Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 5, in ness NameError: global name 'yum' is not defined 

If I do not write it as a function and just type it on the command line one line at a time, it works fine:

 >>> pie='yum' >>> vars()[pie]=4 >>> print vars()[pie] 4 >>> print yum 4 >>> 

Edit: Suppose I wanted to make things a little more complicated than that, and instead of setting yum to a value and printing that value, I define some functions and want to name one of them based on some input:

 def ness(choo): dic={} dessert=() dnum=[10,100] desserts='pie' dic[dessert]=str(desserts[bisect(dnum,choo)]) vars()[dic[dessert]]() def p(): print 'ummmm ummm' def i(): print 'hooo aaaaa' def e(): print 'woooo' 

Therefore, when I call ness, I get a key error:

 >>> ness(3) Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 7, in ness KeyError: 'p' 

Now I know that I can do something like this with some elif statements, but I wonder if this will work, and if using bisect like this would be more efficient (say if I need to check 1000 choo values) than using elifs .

Many thanks for the help.

+3
source share
5 answers

There is a way to do this with exec

 >>> def ness(): ... pie='yum' ... exec pie+"=4" ... print vars()[pie] ... print yum ... >>> >>> ness() 4 4 

But instead, using the new dict is better and safer

 >>> def ness(): ... dic={} ... pie='yum' ... dic[pie]=4 ... print dic[pie] ... print dic['yum'] ... >>> ness() 4 4 >>> 
+2
source

vars() inside the function gives you a local namespace, like locals() - see the docs . Outside of the function (for example, in the tooltip), locals() (and vars() , of course) gives you a global module namespace, like globals() . As docs say, trying to assign a local variable to a function via locals() (or, equivalently, vars() inside a function) is not supported in Python. If you want to assign a global variable, as at the invitation (or otherwise outside the function), use globals() instead of vars() (perhaps not the cleanest approach - global variables are understandably frowned - but it really works).

+4
source

It is not safe to change the dict returned by vars ()

vary ([object]) ΒΆ

With no argument, act like locals ().

With a module, class, or class instance object as an argument (or anything that has a dict attribute), return this attribute.

Note

The returned dictionary should not be changed: effects on the corresponding character table are undefined.

The second example is a special case. vars() equivalent to globals() in the global namespace, and the dict returned by globals() behaves as you expected (but frowned at it)

 >>> id(vars()),id(globals()) (3085426868L, 3085426868L) 
+1
source

vars() equivalent to locals() , which in the case of a function is local variables in its scope and in the interactive interpreter in the scope you have, vars() is globals() . locals() is read-only; the consequences of trying to change it are undefined (and in practice it just doesn't work). globals() can be changed, but you should never directly put anything in the dict that it returns.

0
source

[Edit: I have to be wrong here since "exec" works.]

As everyone notes, it is a bad idea to modify vars (). You can understand this error by realizing that, in a sense, python does not see that "yum" is local. "print yum" is still resolved as a global reference; this happens before any code is executed.

For the same reason, you get an UnboundLocalError:

 >>> y = 100 >>> def foo(x): ... if x == 1: ... y = 10 ... print y ... >>> foo(1) 10 >>> foo(2) Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 4, in foo UnboundLocalError: local variable 'y' referenced before assignment 
0
source

Source: https://habr.com/ru/post/1315824/


All Articles