Python变量作用域
作用域
- Python 中,程序的变量并不是在哪个位置都可以访问的,访问权限决定于这个变量是在哪里定义的。
- 变量的作用域决定了在哪一部分程序可以访问哪个特定的变量名称。
- 变量在作用域中查找的顺序是 L→E→G→B。
作用域的分类
- L(Local):最内层,包含局部变量,比如一个函数/方法内部。
- E(Enclosing):包含了非局部(non-local)也非全局(non-global)的变量。比如两个嵌套函数,一个函数(或类) A 里面又包含了一个函数 B ,那么对于 B 中的名称来说 A 中的作用域就为 nonlocal。
- G(Global):当前脚本的最外层,比如当前模块的全局变量。
- B(Built-in): 包含了内建的变量/关键字等,最后被搜索。
全局变量
- 声明在函数外侧的变量是全局变量,所有函数都可以访问。
- 当全局变量是不可变时,在函数内部修改,需要函数内首行添加global,如果全局变量是可变的,在函数内部修改的时候可以不加global。
- 只访问不修改时,不用加global,同名时,局部变量会屏蔽全局变量。
# 不可变全局变量,在函数内部修改时,需要加global。
# 如果不修改,只访问,无需加global。
m = 10
def test(x, y):
global m # error if no global m
m += 88; x += 10;y += 10
print("inside function m:{}, x:{}, y:{}".format(m, x, y))
return x + y+100
a, b, x, y = 1, 2, 66, 88
test(a, b)
print("outside function m:{}, x:{}, y:{}".format(m,x,y))
result:
inside function m:98, x:11, y:12
outside function m:98, x:66, y:88
# 可变全局变量,在函数内部修改时,可以不加global。
# 函数内部变量会屏蔽掉全局变量。
m = [1,2,3]
a, b, x, y = 1, 2, 66, 88
def test(x, y):
m.append(8); x += 10;y += 10
print("inside function m:{}, x:{}, y:{}".format(m, x, y))
return x + y + 100
test(a, b)
print("outside function m:{}, x:{}, y:{}".format(m,x,y))
result:
inside function m:[1, 2, 3, 8], x:11, y:12
outside function m:[1, 2, 3, 8], x:66, y:88
局部变量
- 函数内部声明的变量,只能在函数内部使用,出了函数不能使用。
- 当局部变量与全局变量重名时,优先局部变量。
- 函数内部的变量可以随便修改,但是要在内部修改不可变全局变量,必须在函数首行声明global。不更改时,不需要声明。
- 在嵌套内部函数中改变外部不可变对象, 需要加nonlocal。
m = 10
list1 = [1, 2, 3]
def foo():
global m
n = 0
list2 = [4, 5, 6]
m += 100
def bar():
global m # 在嵌套内部函数中改变全局不可变对象, 需要加global
nonlocal n # 在嵌套内部函数中改变外部不可变对象, 需要加nonlocal
m += 20
n += 4
list1.append(66)
list2.append(88)
print(m, n, list1, list2)
bar()
print(m, n, list1, list2)
foo()
print(m, list1)
result:
130 4 [1, 2, 3, 66] [4, 5, 6, 88]
130 4 [1, 2, 3, 66] [4, 5, 6, 88]
130 [1, 2, 3, 66]
变量查找顺序
- 在变量访问时,先查找本地变量,然后是嵌套此函数外部的函数体内的变量,之后是全局变量,最后是内建变量。