变量作用域
一个程序的所有变量并不是在哪个位置都可以访问的。访问权限取决于这个变量是在哪里赋值的。
变量的作用域决定了在哪一部分程序可以访问哪个特定的变量名称。
如下为两种最基本的变量的作用域:
- 全局变量
- 局部变量
定义在函数内部的变量拥有一个局部作用域,定义在函数外的拥有全局作用域。
局部变量只能在其被声明的函数内部访问,而全局变量可以在整个程序范围内访问。调用函数时,所有在函数内声明的变量名称都将被加入到作用域中。
举例:
num = 0 #全局变量
def sum(arg1,arg2):
#返回两个参数的和
num = arg1 + arg2 #num在这里是局部变量
print('局部变量:',num)
return num
sum(10,5)
print('全局变量:',num)
执行结果:
-
局部变量: 15 全局变量: 0
python中的作用域分4种情况
- L:local,局部作用域,即函数中定义的变量;
- E:enclosing,嵌套的父级函数的局部作用域,即包含此函数的上级函数的局部作用域,但不是全局的;
- G:globa,全局变量,就是模块级别定义的变量;
- B:built-in,系统固定模块里面的变量,比如int, bytearray等。
- 搜索变量的优先级顺序依次是:作用域局部>外层作用域>当前模块中的全局>python内置作用域,也就是LEGB。
local和enclosing是相对的,enclosing变量相对上层来说也是local;
作用域产生
在Python中,只有模块(module),类(class)以及函数(def、lambda)才会引入新的作用域,其它的代码块(如if、try、for等)是不会引入新的作用域的,如下代码,if并没有引入一个新的作用域,x仍处在当前作用域中,后面代码可以使用:
if 2>1:
x = 1
print(x) #结果为 1
def、class、lambda是可以引入新作用域的:
def test():
x = 2
print(x) #NameError: name 'x' is not defined
global关键字
当内部作用域想修改外部作用域的变量时,就要用到global和nonlocal关键字了,当修改的变量是在全局作用域(global作用域)上的,就要使用global先声明一下,代码如下:
count = 20
def outer():
global count
print(count)
count = 200
print(count)
outer()
执行结果:
-
20 200
nonlocal关键字
global关键字声明的变量必须在全局作用域上,不能嵌套作用域上,当要修改嵌套作用域(enclosing作用域,外层非全局作用域)中的变量就需要nonlocal关键字了:
def outer():
num = 20
def inner():
nonlocal num
num = 100
print(num)
inner()
print(num)
outer()
执行结果:
-
100 100
总结:
(1)变量查找顺序:LEGB,作用域局部>外层作用域>当前模块中的全局>python内置作用域;
(2)只有模块、类、及函数才能引入新作用域;
(3)对于一个变量,内部作用域先声明就会覆盖外部变量,不声明直接使用,就会使用外部作用域的变量;
(4)内部作用域要修改外部作用域变量的值时,全局变量要使用global关键字,嵌套作用域变量要使用nonlocal关键字。nonlocal是python3新增的关键字,有了这个 关键字,就能完美的实现闭包了。