文档章节

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

Lin_R
 Lin_R
发布于 2017/01/08 13:26
字数 560
阅读 1338
收藏 0

上次已经讨论下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

© 著作权归作者所有

Lin_R
粉丝 42
博文 18
码字总数 20310
作品 0
广州
程序员
私信 提问
python try catch

捕获异常的方式 方法一:捕获所有的异常 try: a = b b = c except Exception,data: print Exception,":",data '''输出:<type 'exceptions.Exception'> : local variable 'b' referenced ......

战斗机
2014/04/14
2K
0
python2.7报错

UnboundLocalError: local variable 'table3' referenced before assignment

知行合一1
2017/05/26
65
1
python中遇到错误

1、不能将字典当做key 错误描述:将字典当做key会报如下错误 2、字典取值用dic.get(k),少用dic[k] 错误描述:如果我们用dic[k],当这个key不存在的时候会报KeyError,而用get方法则会返回N...

张欢19933
2016/04/11
55
0
python局部变量和全局变量的问题

fengfeng@fengfeng-Lenovo-XiaoXin-700-15ISK:~$ cat -n test1.py 1 a = 1 2 def do_something(): 3 print a 4 5 do_something() fengfeng@fengfeng-Lenovo-XiaoXin-700-15ISK:~$ python tes......

咧咧976
2016/03/02
161
1
Python全局变量和局部变量的问题

上面的代码在执行的时候会出错,错误信息是: Traceback (most recent call last): File "test.py", line 11, in add(7, 8) File "test.py", line 6, in add print sum UnboundLocalError: l......

ssspure
2016/04/16
307
4

没有更多内容

加载失败,请刷新页面

加载更多

记一次项目启动报java.lang.StackOverflowError

项目是spring boot,之前没有问题,突然有一次debug方式启动的时候报这个错误。 因为其他同事没有问题,线上也没有问题,所以先排除了是代码问题。 开始以为电脑开的软件太多,然后给jvm的内存...

chro008
19分钟前
12
0
idea 2019.2免费激活码

亲测有效到2020.6 812LFWMRSH-eyJsaWNlbnNlSWQiOiI4MTJMRldNUlNIIiwibGljZW5zZWVOYW1lIjoi5q2j54mIIOaOiOadgyIsImFzc2lnbmVlTmFtZSI6IiIsImFzc2lnbmVlRW1haWwiOiIiLCJsaWNlbnNlUmVzdHJpY3Rpb......

Iverson58
27分钟前
7
0
移动APP开发中的重要注意事项

您的移动app在变化吗?如果没有,请确保遵循这些提示进行移动app开发。大多数行业的IT领导者都优先考虑劳动力和消费者的移动性。实现成功的移动app开发具有挑战性,涉及在app功能开发的基础上...

a429011717
34分钟前
6
0
Qt编写自定义控件69-代码行数统计

一、前言 代码行数统计主要用来统计项目中的所有文件的代码行数,其中包括空行、注释行、代码行,可以指定过滤拓展名,比如只想统计.cpp的文件,也可以指定文件或者指定目录进行统计。写完这...

飞扬青云
52分钟前
10
0
驰骋工作流引擎-ccflow关于 “ 是否自动计算未来的处理人”的功能变更

关键字:流程未来节点处理人 工作流快速开发平台 工作流流设计 业务流程管理 asp.net 开源工作流 业务背景:一个流程在启动起来后,是可以对一些节点计算出来处理人是谁,流程的走向。对于另...

孟娟
今天
5
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部