Python vars() global name error

我怕爱的太早我们不能终老 提交于 2019-12-09 03:44:55

问题


I'm having a bit of trouble understanding what's going wrong with the following function:

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

So When I run that 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 don't write it as a function and just type it in on the command line one line at a time it works fine, like so:

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

Edit: Suppose I wanted to make things a bit more complicated than this and instead of setting yum to a value and printing that value, I define some functions, and want to call 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'

So 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 I can do things like this with some elif statements, but I'm wondering if this would work too, and if using bisect like this would be more efficient (say if i need to check 1000 values of choo) than using elifs.

Thanks much for the assistance.


回答1:


There is way to do it with exec

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

But Instead of doing that, using a new dict is better and safe

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



回答2:


vars() within a function gives you the local namespace, just like locals() -- see the docs. Outside of a function (e.g. at the prompt) locals() (and vars() of course) gives you the module's global namespace, just like globals(). As the docs say, trying to assign to a function's local variable through locals() (or equivalently, vars() inside a function) is not supported in Python. If you want to assign to a global variable, as you do when you're at the prompt (or otherwise outside of a function), use globals() instead of vars() (maybe not the cleanest approach -- global variables are understandably frowned upon -- but it does work).




回答3:


It's not safe to modify the dict returned by vars()

vars([object])¶

Without an argument, act like locals().

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

Note

The returned dictionary should not be modified: the effects on the corresponding symbol table are undefined.

Your second example is a special case. vars() is equivalent to globals() in the global namespace, and the dict returned by globals() behaves as you would expect ( but is frowned upon )

>>> id(vars()),id(globals())
(3085426868L, 3085426868L)



回答4:


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




回答5:


[Edit: I must be wrong here, since the 'exec' example works.]

As everyone points out, it's a bad idea to modify vars(). You can understand the error, though, by realizing that python in some sense doesn't "see" that "yum" is a local. "print yum" is still resolved as a global reference; this happens before any code is executed.

It's the same reason you get an UnboundLocalError from:

>>> 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


来源:https://stackoverflow.com/questions/2226386/python-vars-global-name-error

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!