Python vars()全局名称错误

Python vars()全局名称错误,python,global,Python,Global,我在理解以下函数的错误方面有点困难: 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 ne

我在理解以下函数的错误方面有点困难:

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
编辑: 假设我想让事情变得更复杂一点,而不是将yum设置为一个值并打印该值,我定义了一些函数,并希望根据一些输入调用其中一个函数:

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时,我得到一个关键错误:

>>> ness(3)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 7, in ness
KeyError: 'p'
尼斯(3) 回溯(最近一次呼叫最后一次): 文件“”,第1行,在 文件“”,第7行,在ness中 KeyError:'p' 现在我知道我可以用一些elif语句来做类似的事情,但我想知道这是否也可以,并且像这样使用二分法是否比使用elif更有效(比如如果我需要检查choo的1000个值)

非常感谢您的帮助。

这是为了修改vars()返回的dict

变量([对象])

在没有参数的情况下,像本地人一样行事()

以模块、类或类实例对象作为参数(或 任何其他具有命令的内容 属性),返回该属性

不应修改返回的词典:对 相应的符号表如下所示 未定义

你的第二个例子是一个特例
vars()
相当于全局命名空间中的
globals()
,并且
globals()
返回的dict的行为与您预期的一样(但不受欢迎)


函数中的
vars()
为您提供本地名称空间,就像
locals()
--请参阅。在函数外部(例如在提示下)
locals()
(当然还有
vars()
)提供模块的全局名称空间,就像
globals()
一样。比如说,Python不支持尝试通过
locals()
(或者相当于函数内部的
vars()
)分配函数的局部变量。如果您想分配给全局变量,就像您在提示符下(或在函数之外)所做的那样,请使用
globals()
而不是
vars()
(可能不是最干净的方法——可以理解全局变量是不受欢迎的,但它确实有效)。

vars()
相当于
locals()
,在函数的情况下,它是其作用域中的局部变量,而在交互式解释器中,它的作用域是,
vars()是globals()
<代码>局部变量()仅用于读取;试图改变它的效果是不确定的(实际上,就是不起作用)
globals()
可以修改,但是您仍然不应该直接将任何内容放入它返回的dict中。

[编辑:我一定是弄错了,因为“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
>>y=100
>>>def foo(x):
...   如果x==1:
...     y=10
...   打印y
... 
>>>傅(1)
10
>>>傅(2)
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
文件“”,第4行,在foo中
UnboundLocalError:赋值前引用了局部变量“y”

使用exec有一种方法

>>> def ness():
...  pie='yum'
...  exec pie+"=4"
...  print vars()[pie]
...  print yum
...
>>>
>>> ness()
4
4
但与其这样做,不如使用新的dict更好、更安全

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

使用exec为我上面写的更复杂的示例提供了窍门(没有像尝试将dict与VAR一起使用这样的关键错误。到底是什么让使用dict比exec更安全?gnibbler在下面说了什么:“不应该修改返回的字典:对应符号表上的效果未定义”这是否意味着以这种方式使用exec会导致不可预见的问题?exec可以执行任何python代码,例如,`exec“os.system('reboot_your_pc')”,因此最好避免使用它。此外,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
>>>