1.名称空间
将栈区进行分类,这些分类就是名称空间
名称空间 | 存放什么名字 | 空间个数 | 何时创建&销毁 |
内置名称空间built-in | Python解释器内置的名字 | 1个 | Python解释器启动&解释器关闭 |
全局名称空间 global | Python文件内定义的类名,变量名,模块名,函数名等等,排除函数内部定义&内置的 | 多个 | Python文件执行前&文件执行完 |
局部名称空间 local,enclosing | 函数内部定义的名字(包含函数的参数) | 多个 | 函数调用时&调用结束后 |
2.名称空间的加载顺序
内置名称空间 > 全局名称空间 > 局部名称空间
3.为什么要有名称空间?
栈区存在相同变量名的情况下,数据会被覆盖;如果划分空间,就不会产生冲突
4.名称的查找顺序?
- 整体的名称空间优先级:局部名称空间 > 全局名称空间 > 内置名称空间 > NameError
- 查找顺序判断:
- 先判断当前名称是属于哪种名称空间
- 根据所在名称空间开始查找,如没有则向外找
- 注意:查找顺序是以定义阶段为基准的
-
场景1: x = 10 def func1(): print(x) def func2(): x = 20 func1() func2() # 10 在func2内调用func1,func1里面输出x时,func1内部找不到定义的x就去全局空间查找;x=10是先于x=20被定义的 场景2: input = 10 def func1(): def func2(): print(input) func2() input = 20 func1() # 报错NameError,原因是在func1定义内有局部变量input,所以会优先使用该局部变量,但是执行的时候因为变量定义在func2()后,故调用func2的时候查找不到input而报错
-
5.作用域
在名称空间的基础上,按照作用域进行分类: 全局作用域,局部作用域
- 全局作用域:
- 包括:内置名称空间,全局名称空间
- 特点: 全局存活,全局有效
-
场景1: 想要函数内部修改全局变量,需要在变量前定义global---针对不可变类型 (注意:函数内部定义全局变量,就不可再传该参数了) a = 10 def func(): global a a = 5 return a func() print(a) # 5
- 局部作用域:
- 包括: 局部名称空间
- 特点:临时存活,局部有效
- 修改局部变量的值,使用nonlocal,该关键字只会作用在函数内
场景1: 函数内部的局部变量修改,不会影响全局变量
a = 10
def func(a):
a *= 2
func(a)
print(a) # 10
场景2: 针对嵌套函数,想要修改enclosing变量,需要在变量前定义nonlocal----针对不可变类型
def func1():
x = 10
def func2():
nonlocal x
x = 20
func2()
print(x) # 20
func1()
场景3: 嵌套函数无变量,则报错
def func1():
def func2():
nonlocal x
x = 30
func2()
print(x)
func1() # SyntaxError,因为扫描func2定义的时候就去找x所在的空间,func1里面没有则不会再向外去查找,直接报错