3

可能重复:
在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

为什么添加一行我向变量添加一个突然将其从全局变量更改为局部变量?

4

1 回答 1

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,因此存在异常。

于 2013-01-07T18:07:49.387 回答