文档地址:https://docs.python.org/zh-cn/3.6/tutorial/classes.html#python-scopes-and-namespaces
LEGB
python中的变量查找顺序是按照LEGB规则进行查找的,由内往外逐层查找,找到后就不再往后查找,
L:Local,局部作用域,函数内部的作用域
E:Enclosed,局部作用域与全局作用域之间的作用域,例如函数嵌套中的外层函数的作用域
G:Global,全局作用域,所有函数外部的作用域,与模块同层级
B:Built in,内置变量的作用域
global
global用于声明一个非全局变量为全局变量,全局变量在函数内部只可引用不能修改,如果修改也就是出现"="赋值运算,则相当于在函数内部新建了一个与全局变量同名的局部变量,此时引用必须在定义之后,否则会找不到改局部变量而报错。
比如下面这段代码:
a = 10
def fun1():
print(a)
a = 20
def fun2():
a = 20
print(a)
fun1()
fun2()
fun2正常,fun1报错"UnboundLocalError: local variable ‘a’ referenced before assignment",原因是fun1和fun2中a=20相当于声明了一个局部变量,而fun1中先引用后声明所以才会出现上面的错误。
因为fun2中是新建的局部变量,所以说赋值操作不会影响全局变量a的值,a还是等于10,
a = 10
def fun2():
a = 20
fun2()
print(a)
10
如果需要fun2中引用的a是全局变量a,可以使用global关键字在函数内部声明一下,
a = 10
def fun2():
global a
a = 20
print(a)
fun2()
print(a)
10
20
global关键字在函数内部声明变量的时候,这个变量可以在全局作用域中未定义,此时相当于在函数内部新建了一个全局变量,
def fun():
global a
a = 20
fun()
print(a)
20
nonlocal
nonlocal关键字用于在局部作用域里面引入Enclosed作用域里面的变量(该作用域里离自己最近的那个同名变量),被nonlocal修饰的变量要求在Enclosed作用域中必须存在,否则报错。在局部作用域里对经nonlocal修饰的变量进行修改删除等操作,操作的都是外层Enclosed作用域中的变量。
下面是局部作用域中修改nonlocal修饰的变量,
def fun1():
a = 10
def fun2():
nonlocal a
a = 20
fun2()
print(a)
fun1()
20
nonlocal修饰的变量在Enclosed作用域之间必须存在,可以越级,系统会从Enclosed作用域中由内往外,引入离局部作用域最近的那个同名变量,
def fun1():
a = 10
def fun2():
def fun3():
nonlocal a
a = 20
fun3()
fun2()
print(a)
fun1()
20
如果变量a在Enclosed作用域中不存在,比如说把a调换到全局作用于当中,就会报错,
a = 10
def fun1():
def fun2():
def fun3():
nonlocal a
a = 20
fun3()
fun2()
print(a)
fun1()
SyntaxError: no binding for nonlocal 'a' found