一直觉得python的作用域不是什么难点,但是前几天在另一个博客平台上看到一段代码,又把我弄糊涂了,于是看书,把作用域又看了一遍,重新总结一下知识要点和坑,做个笔记
所有代码基于python2.7.10
基本概念和知识点不多说,直接上代码:
bar = 200
def foo():
print bar
foo() # 200
这段代码是没有错的,再看看下面一段:
bar = 200
def foo():
bar = 100
print bar
foo() # 100
foo()中声明了局部变量bar,所以最后打印的是100,这也是毋庸置疑的
但是再看看下面的代码,也是让我感到迷惑的代码:
bar = 200
def foo():
print bar
bar = 100
foo() # 出现错误
出现异常UnboundLocalError: local variable ‘bar’ referenced before assignment
这让我有点迷惑,这和我想的有点不一样,于是在书上找到了这样的解释:
当使用全局变量同名的局部变量的时候要小心.如果在赋予局部变量值之前,你在函数中(为了访问这个全局变量)使用了这样的名字,你将会得到一个异常(NAMEERROR或者Unbound-LocalError),抛出哪个异常取决与python版本.
这样的代码确实也是很让人迷惑,全局变量和局部变量全搅乱了,python直接抛出异常的行为我觉得是很好的:直接就不让你写这样的代码.
但是如果真有这种情况呢,就要使用global关键字了.声明为全局变量,然后随便你怎么折腾:
bar = 200
def foo():
global bar
print bar
bar = 100
print bar # 200
foo() # 200
print bar # 100
这就很清楚了.如果global不是位于函数的顶部,而是使用或赋值变量之后,会有警告:
bar = 200
def foo():
print bar
global bar
bar = 100
foo() # 200
会出现警告:
SyntaxWarning: name ‘bar’ is used prior to global declaration
global bar
这样也会有警告:
bar = 200
def foo():
print bar
bar = 100
global bar
foo() # 200
print bar # 100
警告和之前不一样:
SyntaxWarning: name ‘bar’ is assigned to before global declaration
global bar
最后print bar 的结果是100,也就是说全局变量bar被改成了100.
在foo里虽然是先有bar = 100
然后才有global bar
但bar仍然被当作全局变量赋值为100.