Python变量解析

时间:2010-08-19 20:35:57

标签: python

给出以下代码:

a = 0
def foo():
  # global a
  a += 1
foo()

运行时,Python抱怨:UnboundLocalError:在赋值之前引用的局部变量'a'

但是,当它是字典时......

a = {}
def foo():
  a['bar'] = 0
foo()

事情运行得很好......

任何人都知道为什么我们可以在第二块代码中引用一个,但不是第一个?

4 个答案:

答案 0 :(得分:2)

不同之处在于,您在分配给a的第一个示例中创建了一个隐藏全局a的新本地名称a

在第二个示例中,您没有对a进行分配,因此使用了全局a

documentation

中介绍了这一点
  

Python的一个特殊之处在于 - 如果没有全局语句生效 - 对名称的赋值总是进入最内层范围。

答案 1 :(得分:1)

问题是更新。

您无法更新a,因为它不是函数本地命名空间中的变量。就地更新分配操作无法更新a

有趣的是,a = a + 1也失败了。

Python为这些语句生成稍微优化的代码。它使用“LOAD_FAST”指令。

  2           0 LOAD_FAST                0 (a)
              3 LOAD_CONST               1 (1)
              6 INPLACE_ADD         
              7 STORE_FAST               0 (a)
             10 LOAD_CONST               0 (None)
             13 RETURN_VALUE        

请注意,在等号的左侧和右侧使用a会导致此优化。

但是,您可以访问a,因为Python会为您搜索本地和全局命名空间。

由于a未出现在赋值语句的左侧,因此使用了另一种访问类型“LOAD_GLOBAL”。

  2           0 LOAD_CONST               1 (0)
              3 LOAD_GLOBAL              0 (a)
              6 LOAD_CONST               2 ('bar')
              9 STORE_SUBSCR        
             10 LOAD_CONST               0 (None)
             13 RETURN_VALUE        

答案 2 :(得分:0)

a += 1相当于a = a + 1。通过分配变量a,它变为本地变量。您尝试分配a + 1的值失败,因为a尚未绑定。

答案 3 :(得分:0)

这是一个非常常见的Python问题:如果你在一个函数中分配一个变量(正如你所做的那样,使用+=),任何地方(在你使用它之前不一定)另一种方式),它不使用全局的。但是,由于您所做的实际上是“a = a + 1”,因此您在分配之前尝试访问a(在表达式的右侧)。

尝试在函数开头使用global a(但请注意,您将覆盖全局a值。)

在第二个示例中,您没有分配变量a,而只分配给其中一个项目。所以使用了全局字典a