引入
栈区 / 堆区
- 栈区 : 存放的是变量名与变量值的内存地址映射关系
- 堆区 : 存放的是值真正的位置
一.名称空间
1.什么是名称空间
- 存放名字与值绑定关系的地方
- 名称空间是一个虚拟的概念, 栈区才真实存在
2.为什么要有名称空间
- 有了名称空间后就可以在内存的栈区存放相同的名字, 并且不会冲突
3.名称空间是否有包含关系?
- 名称空间本质之间是没有包含关系的, 并且相互独立
二.名称空间的分类(三类)
1.内置名称空间
- 存放内置的名字
- 周期 : 在解释器启动时就产生,解释器关闭则失效
🎅例如我们常用的内置函数
print
len
input
2.全局名称空间
- 存放的是顶级的名字 (文件级别的名字)
- 周期 : 在执行文件时生效,文件运行完毕或文件执行期间被删除则失效
x = 1 #全局名称空间
def foo(): #全局名称空间
y = 2
🎅注意,"if"下面的定义的变量名都是全局的
if 1 > 0
z = 3 #全局
if 3 > 0:
p = 555 #全局
3.局部名称空间
- 存放函数内定义的名字
- 周期 : 在函数调用时临时生效, 函数结束时则失效
def f()
x = 222 #局部名称空间
f() #函数调用结束失效
4.名称空间的加载顺序
'内置名称空间'----->'全局名称空间'----->'局部名称空间'
5.名称空间的查找优先级
'局部名称空间'----->'全局名称空间'----->'内置名称空间'
6.名称空间的销毁顺序
'局部名称空间'----->'全局名称空间'----->'内置名称空间'
7.名称空间总结与注意事项
-
重要概念:名称空间的嵌套关系是在函数定义阶段(检测语法)时确定的,与函数调用的位置无关,与函数定义位置有关
-
三种名称空间必须要有的是 : 内置名称空间, 全局名称空间
-
查找优先级示例
🎅从"f2"局部开始找
x = 3
def f1():
x = 2
def f2():
x =1
print(x)
f2()
f1() # 1
🎅将"f2"局部的删除,就往上一层找,找到"f1"
x = 3
def f1():
x = 2
def f2():
print(x)
f2()
f1() # 2
🎅再将"f1"里面的删除,于是找到了全局
x = 3
def f1():
def f2():
print(x)
f2()
f1() # 3
- 函数的嵌套定义示例
🎅在定义"f2"的之后,有定义了同一级别的"len",所以当打开函数"f2"运行的时候,本着优先级查找就先找到了"222"
len = 111
def f1():
def f2():
print(len) # 222
len = 222
f2()
f1() # 222
三.作用域
1.什么是作用域
- 作用域就是根据名称空间的范围和特点进行了归类
- 查看作用域 : globals( ), locals( )
2.全局作用域
- 包含 : 内置名称空间, 全局名称空间
- 特点 : 全局存活, 全局有效
3.局部作用域
- 包含 : 局部名称空间
- 特点 : 临时存活, 局部有效
4.L E G B
- LEGB 代表名字查找顺序 : L—>E—>G—>B
- locals : 是函数内的名字空间, 包括局部变量和形参
- enclosing : 外部嵌套的名称空间(闭包中常见面)
- globals : 全局变量, 函数定义所在模块的名字空间
- builtins : 内置模块的名字空间
四.global 与 nonlocal关键字
1.global 关键字
- 使用方法 : global x 声明这个 x 是全局变量
- 针对的是不可变类型的值
🎅在全局空间定义一个变量"x",函数"foo",在函数内部修改"x"的值
x = 111
def foo():
x = 222
foo()
print(x) #111
#发现并无软用
🎅使用"global"关键字之后
x = 111
def foo():
global x # 声明下面的"x"属于全局
x = 222
foo()
print(x) #222
#发现成功了
2.nonlocal 关键字
- 使用方法 : nonlocal x
- 修改该函数外层函数包含的变量名对应的值, 也是针对不可变类型
- 注意 : 只能在局部名称空间中查找, 先从外部嵌套的函数找, 没找到再往上找, 如果都没找到则报错
🎅不做任何处理,此函数应该是打印"f2"函数下的"x = 333"
x = 111
def f1():
x = 222
def f2():
x = 333
def f3():
x = 444
f3()
print(x) #333
f2()
f1() # 333
🎅使用"nonlocal"关键字
x = 111
def f1():
x = 222
def f2():
x = 333
def f3():
nonlocal x #将下面的"x = 444"变成了上一层的"x"的值
x = 444
f3()
print(x)
f2()
f1() # 444
🎅如果外层函数都没有"x"这个值,报错
x = 111 #并不会去全局修改
def f1():
def f2():
def f3():
nonlocal x
x = 444
f3()
print(x)
f2()
f1() #报错