2010-02-09 63 views
3

我有一点很难理解什么是用下面的函数脚麻:Python的瓦尔()全局名称错误

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

所以,当我跑,我得到这样的结果:

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

如果我不把它写成一个函数,只需键入它在命令行上一次在一个行,它工作正常,像这样:

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

编辑: 假设我想使事情比这更复杂,而不是百胜设定的值并打印该值,我定义了一些功能,并希望基于一些输入调用其中的一个:

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' 

所以,当我打电话内斯我得到一个关键的错误:

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

现在我知道我可以做这样的事情了一些ELIF语句,但我不知道这是否会工作太时,如果使用开张像这样会比使用elifs更高效(比如说,如果我需要检查1000个choo值)。

非常感谢您的帮助。

回答

2

有办法以exec做

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

而是做着的是,采用了全新的字典是更好的安全

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

使用exec做了上面写的更复杂的例子的窍门(没有像我们试图给我们的关键错误电子词典以及变量。究竟使用dict比exec更安全?是什么gnibbler说: “返回的字典不应该被修改:对相应的符号表的影响是不明确的” 这意味着使用exec这种方式可能会导致不可预见的问题? – Jamie 2010-02-09 15:17:12

+0

exec可以执行任何python代码,例如'exec“os.system('reboot_your_pc')”,所以最好避免使用它。 – YOU 2010-02-09 15:49:42

+0

另外exec可以给你一个令人困惑的stacktrace,并且比明确的字典要慢得多(它必须从头开始解析)。 – viraptor 2010-02-28 17:50:13

1

这是not safe修改()由瓦尔返回的字典

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.

你的第二个例子是一个特例。 vars()相当于globals()在全局命名空间,并通过globals()返回的字典表现为你所期望的(但是是不可取的)

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

vars()函数内给你当地的命名空间,就像locals() - 见the docs。功能之外(例如在提示时)locals()(当然还有vars())为您提供模块的全局命名空间,就像globals()一样。正如the docs所说,在Python中不支持通过locals()(或等效地,在函数内部的vars())尝试分配给函数的局部变量。如果你想分配给全球变量,你当你做在提示符下(或以其他方式功能之外),使用globals()代替vars()(也许不是最干净的方法 - 全局变量应是可以理解皱起眉头 - 但它确实有效)。

0

vars()相当于locals(),该函数在其范围内是局部变量,在交互式解释程序中是vars() is globals()locals()仅供阅读;试图改变它的效果是不确定的(实际上,它不起作用)。 globals()可以进行修改,但你仍然应该从未直接放任何东西在它返回的字典。

0

[编辑:我一定是错的,因为'exec'的例子有效。]

正如大家指出的那样,修改vars()是一个坏主意。但是,通过认识到python在某种意义上不会“看到”“yum”是本地的,你可以理解错误。 “print yum”仍然是作为全球参考解决的;这发生在任何代码执行之前。

这是你从得到一个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 
相关问题