Python变量作用域

这里小秦来研究下作用域(scope)的问题。

python通过一个变量被赋值的位置来决定这个变量的scope。对于function来说,每个function中的变量会和这个function的scope关联,而不是global的namespace。比如下面这个例子:

a = 100

def func():
	b = 200

这里a的scope就是这个file,而b的scope就是func。

在python中,只有模块,类以及函数才会引入新的作用域,其它的代码块是不会引入新的作用域的。因此这个和C语言中的{}引入作用域不同,比如python中的if、for等语句就没有作用域,因此下面的代码是可以正常运行的:

for i in range(0,10):
    pass
    
print i

对于2.1之后的python来说,主要有下面四种scope:
local:比如function中的变量所在的作用域就是local的。简称L
enclosing:某个function被嵌套后的上一层function的作用域。简称E
global:当前模块中的全局作用域。简称G
built-in:python内置作用域.简称B
对某个变量搜索的顺序是:local>enclosing>global>built-in。也就是LEGB

如果想内层的变量域中的代码想修改global中的变量值,使用global关键字。如果内层的变量域中的代码想修改enclosing中的变量值,使用nonlocal关键字。如果没有使用这两个关键字,那么在对其进行修改(也就是对其再次赋值的时候)会生成局部变量进行赋值,并且在本作用域使用的时候会覆盖高层作用域的值,但不影响高层作用域中的值。比如:

a = 100

def func01():
    print a

func01()
a = 100

def func01():
    print a
    a = 200

func01()

这里第一个例子不会报错,会输出100,因为a回去上层作用域中查找。而第二个例子会报错,因为在预编译的时候,由于python发现对a进行了赋值,因此认为a是个局部变量。但是运行到print的时候a还没有被赋值,所以就报错了。如果要避免的话,可以用下面这个例子:

a = 100

def func01():
    global a
    print a
    a = 200
    print a

    b = 300
    def func02():
        nonlocal b
        print b
        b = 400
        print b

    func02()
    print b

func01()

参考http://www.cnblogs.com/frydsh/archive/2012/08/12/2602100.html这篇文章,可以看到python对变量和作用域的绑定时机:
在Python中,名字绑定在所属作用域中引入新的变量,同时绑定到一个对象。名字绑定发生在以下几种情况之下:
1.参数声明:参数声明在函数的局部作用域中引入新的变量;
2.赋值操作:对一个变量进行初次赋值会在当前作用域中引入新的变量,后续赋值操作则会重新绑定该变量;
3.类和函数定义:类和函数定义将类名和函数名作为变量引入当前作用域,类体和函数体将形成另外一个作用域;
4.import语句:import语句在当前作用域中引入新的变量,一般是在全局作用域;
5.for语句:for语句在当前作用域中引入新的变量(循环变量);
6.except语句:except语句在当前作用域中引入新的变量(异常对象)。
在Python中,类定义所引入的作用域对于成员函数是不可见的,这与C++或者Java是很不同的,因此在Python中,成员函数想要引用类体定义的变量,必须通过self或者类名来引用它。嵌套作用域的加入,会导致一些代码编译不过或者得到不同的运行结果,在这里Python解释器会帮助你识别这些可能引起问题的地方,给出警告。

另外在3.X的python中,有nonlocal关键字,类似于global,用于在嵌套函数中修改父级函数的变量。

发表评论

电子邮件地址不会被公开。 必填项已用*标注

*