python中的局部/全局变量混淆

时间:2013-01-07 18:05:31

标签: python

  

可能重复:
  referenced before assignment error in python

我在python中遇到一个奇怪的错误。以下ipython日志总结了它:

In [10]: def confused(stuff):
   ....:     print huh
   ....:     return stuff
   ....: 

In [11]: confused(87)
0
Out[11]: 87

In [12]: def confused(stuff):
   ....:     print huh
   ....:     huh += 1
   ....:     return stuff
   ....: 

In [13]: confused(9)
---------------------------------------------------------------------------
UnboundLocalError                         Traceback (most recent call last)
/home/max/verk/btr-email/build/x86_64/bin/ipython in <module>()
----> 1 confused(9)

/home/max/verk/btr-email/build/x86_64/bin/ipython in confused(stuff)
      1 def confused(stuff):
----> 2     print huh
      3     huh += 1
      4     return stuff

UnboundLocalError: local variable 'huh' referenced before assignment

有效的函数和抛出错误的函数之间的唯一区别是+ = 1行,即使这样,它也会在以前工作的行上引发错误!如果我在方法的第二个版本中引用global huh之前放置huh,也不会抛出错误。

为什么添加一行我在变量中添加一行会突然从全局变量变为局部变量?

1 个答案:

答案 0 :(得分:7)

在您的脚本中,huh指的是全局变量。您无法将引用更改为函数中的全局变量,而无需明确告知python您想要执行的操作:

def confused(stuff):
    global huh
    print huh
    huh += 1
    return stuff

对于诸如整数,字符串,浮点数等不可变对象,这意味着您无法在不将其声明为global的情况下对对象进行任何更改。对于可变对象,您可以更改对象项或属性,但仍然无法更改对象的引用


这是范围的问题。由于huh不在confused的本地范围内,因此python会在全局范围内找到它。由于它是在全局范围内找到的,因此除非您明确表示要(正如我上面所做的那样使用global),否则不能指定。但是,如果它是list,则一旦找到列表,您就可以访问该列表的所有方法(包括__setitem__append等。)


关于错误的位置,可以通过稍微dis组装来清除:

>>> def confused(stuff):
...    print huh
... 

>>> import dis
>>> dis.dis(confused)
  2           0 LOAD_GLOBAL              0 (huh)
              3 PRINT_ITEM          
              4 PRINT_NEWLINE       
              5 LOAD_CONST               0 (None)
              8 RETURN_VALUE

>>> def confused2(stuff):
...    print huh
...    huh += 1
... 

>>> dis.dis(confused2)
  2           0 LOAD_FAST                1 (huh)
              3 PRINT_ITEM          
              4 PRINT_NEWLINE       

  3           5 LOAD_FAST                1 (huh)
              8 LOAD_CONST               1 (1)
             11 INPLACE_ADD         
             12 STORE_FAST               1 (huh)
             15 LOAD_CONST               0 (None)
             18 RETURN_VALUE   

你可以看到在confused2中,python已经在函数的第一行尝试LOAD_FAST(意思是寻找局部变量)。但是,没有局部变量huh因此存在异常。