名称空间与作用域
名称空间
名称空间分为全局名称空间、局部名称空间和内置名称空间
全局名称空间:存放的是py文件中变量与值的对应关系
局部名称空间:存放的是函数体里面的变量与值的对应关系
内置名称空间:存放内置函数,关键字等
作用域
全局作用域:内置名称空间、全局名称空间
局部作用域:局部名称空间
python代码执行过程中是怎样存储对象的呢
对于变量
1. 遇到初始化对象命令,创建名称空间,保存变量与值的对应关系
2. 存放的是变量名和值的内存地址
对于函数
1. 遇到函数定义,只是在名称空间里存放函数名,此时对于函数内部的变量是不关心的
2. 遇到函数执行,创建临时名称空间(局部名称空间),临时名称空间随着函数的结束而消失
加载顺序与取值顺序
加载顺序:就是加载在内存中的顺序
1. 内置名称空间
2. 全局名称空间
3. 局部名称空间
取值顺序
1. 局部名称空间
2. 全局名称空间
3. 内置名称空间
取值顺序也称为LEGB规则
L:Local 局部名称空间
E: Enclosed 父级名称空间
G: Global 全局名称空间
B: Built-in 内置名称空间
globals()与locals()
globals()和locals()是内置函数,其功能如下:
globas(): 返回一个字典,包括全局作用域的内容
locals(): 返回一个字典,包括当前作用域的内容
实例1:
1 def func(): 2 name = "barry" 3 age = 18 4 print(globals()) 5 print(locals()) 6 7 8 func()
执行结果
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x0000027DED6DA400>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'D:/名称空间与加载顺序.py', '__cached__': None, 'func': <function func at 0x0000027DED7A9B70>} {'age': 18, 'name': 'barry'}
实例2:
动态参数*args与**kwargs
*args和**kwargs可以接收任意数量的参数,args接收位置参数,kwargs接收关键字参数
1 def func(*args, **kwargs): # 在函数的定义时,*, **代表聚合 2 print(args) 3 print(kwargs) 4 5 6 func(*[1, 2, 3], *"abc", **{"name": "Robin", "age": 18}, gender="female") # 函数的执行时,*, **代表打散
执行结果
(1, 2, 3, 'a', 'b', 'c') {'name': 'Robin', 'age': 18, 'gender': 'female'}
在函数的定义时,*和**表示聚合,*将位置参数聚合成元组,**将关键字参数聚合成字典;在函数执行时,*和**表示打散
在python3.6中,*的适用范围扩展到非函数领域
1 a, b, *args = [i for i in range(10)] 2 print(a, b, args) 3 4 a, b, *args = (1, 2, 3, 4, 5, 6) # *args会将多余的参数放到一个列表里(只会是列表) 5 print(a, b, args)
输出
0 1 [2, 3, 4, 5, 6, 7, 8, 9]
1 2 [3, 4, 5, 6]
global与nonlocal
global和nonlocal是两个关键字,注意不要与globals()和locals()弄混了
global
1. 声明一个局部变量
2. 在局部作用域内对全局变量进行操作
1 name = "Bill" 2 3 4 def func(): 5 global name 6 name = "Alice" 7 8 9 func() 10 print(name)
执行结果
Alice
nonlocal
正常来说局部作用域对全局作用域的变量只能引用而不能修改
1 count = 1 2 3 4 def func(): 5 print(“count:", count) # 可以打印 6 7 8 func()
执行结果
count: 1
1 count = 1 2 3 4 def func(): 5 # print("count:", count) # 可以打印 6 count += 1 # 报错 7 8 9 func()
执行结果
UnboundLocalError: local variable 'count' referenced before assignment
除了局部作用域不能修改全局作用域之外,内层函数也不能修改外层函数的变量,如果要修改那么要用到nonlocal
nonlocal作用
1. 在局部作用域中,对父级作用域(或者更外层作用域非全局作用域)的变量进行引用和修改
2. 引用的哪层,从哪层以下此变量全部发生更改
1 def wrapper(): 2 name = 'alex' 3 4 def inner(): 5 nonlocal name 6 name += 'b' 7 print(name) 8 print('1', name) 9 inner() 10 print('2', name) 11 12 13 wrapper()
执行结果
1 alex
alexb
2 alexb
函数嵌套
这个没啥难的,只要记住两点