明确一点,一个变量的作用域总是在被赋值的地方所决定。能直接改变变量作用域的有def、class、lambda,if、while、for不能直接改变变量作用域。
一、LEGB准则(LNGB准则)
这里重点讨论def语句,我们定义的变量实际上只有三种不同的作用域:
- 在def内部赋值,它被定为在函数内部,为本地Local
- 在一个嵌套的def中赋值,对于嵌套函数来说,它是非本地的Nonlocal
- 在def外部赋值,它就是整个文件全局的Global
L:Local、E:Enclose、G:Global、B:Built-in
根据LEGB准则,在函数内使用未认证的变量时,Python按照LEGB准则,依次搜索,直到第一次能找到这个变量的地方停下。
x = 100
def foo():
x = 99
print(x)
if __name__ == '__main__':
foo()
结果为
99
foo()内创建局部变量x跟全局变量x同名,foo()优先搜索局部变量x,输出99
x = 100
def foo():
x = 99
def bar():
x = 98
print(x)
bar()
if __name__ == '__main__':
foo()
结果
98
调用foo(),返回bar(),bar()内部创建local变量x=98,对于bar()而言x=99是enclose,x=100是global的
优先输出local的x值98
如果删掉x=98,则会优先搜索E
x = 100
def foo():
x = 99
def bar():
print(x)
bar()
if __name__ == '__main__':
foo()
结果是
99
非常类似C语言的局部作用域屏蔽全局作用域
二、global、nonlocal语句
x = 100
def foo():
global x
x = 99
if __name__ == '__main__':
foo()
print(x)
结果是
99
global语句允许def内部的x直接引用全局变量 x,并且修改了对象的值