名称空间和作用域
一、名称空间
名称空间:就是存放名字和对象映射/绑定关系的地方(存放名字的空间)
如果你想访问一个变量值,必须先访问对应的名称空间拿到名字和对应的内存地址的绑定地址
-
名称空间的分类
- 内置名称空间
Python提前给你定义完的名字,就是存在内置名称空间,比如内建函数名
>>> max <built-in function max> >>> >>> print <built-in function print> >>> >>> input <built-in function input>
- 全局名称空间
存放于文件级别的名字,就是全局名称空间
if、while、for内部定义的名字执行之后都存放于全局名称空间
- 局部名称空间
函数内部定义的所有名字都市存放于当前函数的内置名称空间
def foo(x): y = 1 #调用函数时,才会执行函数代码,名字x和y都存放于该函数的局部名称空间中
-
名称空间的顺序
- 加载顺序为:内置 > 全局 > 内置
- 查找顺序为:局部 > 全局 > 内置
函数内部使用的名字,定义阶段已经规定死了,与调用位置无关
-
生命周期
- 内置名称空间
在Python解释器启动的时候生效,关闭解释器的时候失效
- 全局名称空间
当你启动当前这个py文件的时候生效,当页面代码执行结束之后失效
- 局部名称空间
当你调用当前函数时生效,函数体最后一行代码执行结束之后失效
二、作用域
按照名字作用范围的不同可以将三个名称空间划分为两个区域:
- 全局作用域
位于全局名称空间、内建名称空间中的名字属于全局范围,该范围内的名字全局存活(除非被删除)、全局有效(在任意位置都可以使用)
【全局可以调用的名字就存放于全局作用域】【内置名称空间+全局名称空间】
x = 100
def foo():
x = 300 #函数调用时产生局部作用域的名字x
foo()
print(x) #在全局找x,结果为100
在全局作用域查找名字时,先查找全局名称空间,没有找到,再查找内置名称空间,最后都没有找到就会抛出异常
- 局部作用域
位于局部名称空间中的名字属于局部范围。该范围内的名字临时存活(在函数调用时临时生成,函数调用结束后释放)、局部有效(只能在函数内使用)
【局部可以调用的名字就存放于局部作用域】【局部名称空间】
x = 100 #全局作用域的名字x
def foo():
x = 300 #局部作用域的名字x
print(x) #在局部找x
foo() #结果为300
在局部作用域查找名字时,先查找全局名称空间,没有找到,再查找内置名称空间,最后都没有找到就会抛出异常
- 关键字global
声明全局变量
x = 1
def foo():
global x #声明x为全局名称空间的名字
x = 2
foo()
print(x)
2
- 关键字nonlocal
在局部名称空间声明局部变量,在局部修改上层函数的变量
只有可变类型可以在局部修改外部变量的值
def f1():
x = 2
def f2():
nonlocal x
x = 3
f2() #调用f2(),修改f1作用域中名字x的值
print(x) #在f1作用域查看x
f1()
3
nonlocal x 会从当前函数的外层函数开始一层层去查看名字x,若是一直到最外层函数都找不到,则会抛出异常