作用域就是一个 Python 程序可以直接访问命名空间的正文区域。
在一个 python 程序中,直接访问一个变量,会从内到外依次访问所有的作用域直到找到,否则会报未定义的错误。
Python 中,程序的变量并不是在哪个位置都可以访问的,访问权限决定于这个变量是在哪里赋值的。
变量的作用域决定了在哪一部分程序可以访问哪个特定的变量名称。Python 的作用域一共有4种,分别是:
有四种作用域:
- L(Local):最内层,包含局部变量,比如一个函数/方法内部。
- E(Enclosing):包含了非局部(non-local)也非全局(non-global)的变量。比如两个嵌套函数,一个函数(或类) A 里面又包含了一个函数 B ,那么对于 B 中的名称来说 A 中的作用域就为 nonlocal。
- G(Global):当前脚本的最外层,比如当前模块的全局变量。
- B(Built-in): 包含了内建的变量/关键字等,最后被搜索。
搜索变量名的优先级: L –> E –> G –> B。(局部作用域>嵌套作用域>全局作用域>内置作用域)
LEGB法则:当在函数中使用未确定的变量时,Python会按照优先级依次搜索4个作用域,以此来确定变量的意义。首先搜索局部作用域(L),之后是上一层嵌套结构中def或lambda函数的嵌套作用域(E),之后是全局作用域(G),最后是内置作用域(B)。按照这换个查找原则,在第一处找到的地方停止。如果没有找到,则会触发NameError错误。在局部找不到,便会去局部外的局部找(例如闭包),再找不到就会去全局找,再者去内置中找。
1 #作用域 2 a1 = 10 #全局作用域 3 def pri(): 4 print(a1) 5 pri() 6 7 8 def pri1(): 9 a2 = 20 #局部作用域 10 print(a2) 11 pri1() 12 #print(a2) #这句这样写则会报错,因为a2的作用域只在函数内部并不是全局作用域,注意区别 13 14 15 #嵌套作用域 16 def f1(): 17 n = 10 #在f1函数中,是局部作用域 相对于f2函数,是嵌套作用域 18 def f2(): 19 m = 20 #局部作用域 20 print(n) 21 f2() 22 23 24 #内置作用域 系统自带 25 print(__name__) #内置作用域
1 #搜索变量名的优先级:局部作用域>嵌套作用域>全局作用域>内置作用域 2 #LEGB法则:当在函数使用未确定的变量名时,Python会按照优先级依次搜索4个作用域, 3 # 以此来确定该变量的意义。首先搜索局部作用域(L),之后是上一层嵌套结构中def或lambda 4 # 函数的嵌套做作用域(E),之后是全局作用域(G),最后是内置作用域(B)。按照这个查找原则, 5 # 在第一处找到的地方停止。如果没有找到,则触发NameError错误。 6 a1 = 10 # G 7 def f1(): 8 a1 = 20 # E 9 def f2(): 10 a1 = 30 # L 11 print(a1) 12 f2() 13 f1() 14 15 16 #******************************************** 17 a1 = 10 # G 18 def f1(): 19 a1 = 20 # E 20 def f2(): 21 # a1 = 30 # L 22 print(a1) 23 f2() 24 f1() 25 # ******************************************** 26 a1 = 10 # G 27 def f1(): 28 # a1 = 20 # E 29 def f2(): 30 # a1 = 30 # L 31 print(a1) 32 f2() 33 f1() 34 35 # ****************************************** 36 37 a2 = 100 38 def f3(): 39 global a2 #使用global将全局变量a2的地址给引用过来了,就会改变全局变量的值 40 a2 = 60 41 print(a2) 42 f3() 43 print(a2) #查看全局变量a2确实是变了,变成了60