说下那神奇的 UnboundLocalError: local variable x referenced before assignment

2017-01-09 14:10:50来源:oschina作者:Lin_R人点击

上次已经讨论下python 作用域 和LEGB的关系,https://my.oschina.net/u/2291453/blog/820865


接下来讨论下 我们经常会遇到的报错:referenced before assignment


简单的代码:


# coding: utf8
a = 3
def f():
print a
a = 4
print a
f()
print '---------------------分割线--------------------'
a = 3
def f():
a += 4
print a
f()

不管是第一段代码,还是第二段代码, 都无一幸免得出如下信息:


UnboundLocalError: local variable 'a' referenced before assignment

Oh~no, 为什么会报错!! 应该都能从全局变量去获取啊!!


其实这种现象很好解释, 因为虽然是代码执行是顺序的, 但是作用域的判断却不是, Python是采用静态作用域,而不是动态作用域, 换言之, 只需要从代码正文就能看出变量需要从哪个作用域引用.


于是, 不管是第一段还是第二段, python已经在函数内部作用域找到了对符号a的约束语句, 所以已经不会从global查到了, 但是由于代码执行是顺序的, 只有在执行到赋值语句, 约束才能真正建立, 但是在此之前, 符号a已经能够在名字空间找到, 只是未定义而已


a += 4 这句代码看似很符合上面说到的, 但是为什么也会报错, 其实原因就是, 虽然说代码的执行是自上而下, 自左向右执行, 但是对于赋值语句, 就不是自左向右, 而是自右向左


a += 4 ===> a = a + 4 (转换)


经过上面的转换, 我们能够看得更加清楚, 首先执行 a+4 , 然后再执行赋值, 好了, 于是执行a + 4时, 查找a, 发现能够在名字空间找到了, 但却未定义, 那自然而然也就报错退出了


而在代码中使用global 对变量声明下, 则能避免这个问题, 因为global的声明, 将会强制python去global名字空间查找, 而不用再管LEGB原则, 不过要主要这样也会修改全局变量的值哦, 慎用~


欢迎各位大牛指点教育, 转载请注明:https://my.oschina.net/u/2291453/blog/820866

最新文章

123

最新摄影

微信扫一扫

第七城市微信公众平台