python之名称空间与作用域
名称空间
名称空间就是变量名与变量值绑定关系的地方。比如对于x=1,1存放于内存空间,而x与1的对应关系存储在名称空间中。
名称空间分为三类:内置名称空间、全局名称空间、局部名称空间。
内置名称空间
内置名称空间存储的是python解释器提前给我们定义好的,像len()、print()、open()等。
存活周期:python解释器运行则产生,关闭则销毁。
全局名称空间
名字只要不是在函数里的运行产生的,都会存到全局名称空间。
name = 'jason' # 变量名name存入全局名称空间
def index(): # 函数名index存入全局名称空间
pass
if True:
a = 111 # 变量名a存入全局名称空间
for i in range(10): # 变量名i存入全局名称空间
pass
while True:
b = 222 # 变量名b存入全局名称空间
存活周期:python文件开始运行时产生,运行完毕时销毁。
局部名称空间
名字只要是在函数里的运行产生的,都会存到局部名称空间。
def index():
name = 'jason' # 变量名name存入局部名称空间
存活周期:函数被调用时产生,函数调用结束时销毁。
名称的查找顺序
如果要去找一个名称,有这么多个名称空间,我们该去那个名称空间找呢?
在查找名称之前,要先知道直接在哪一个空间内。知道了自己所在的空间后,先在自己空间内查找,找不到在向外寻找,所以查找顺序应该是:局部名称空间 >>> 全局名称空间 >>> 内置名称空间
# 案例一
len = '我是全局名称空间中的len'
def index():
len = '我是局部名称空间中的len'
print(len) # 输出:我是局部名称空间中的len
index() # 调用函数 函数体就会执行 就会产生局部名称空间
print(len) # 输出:我是全局名称空间中的len
# 案例二
x = 111
def f1():
x = 222
def f2():
x = 333
print(x)
f2()
f1() # 输出:333
作用域
作用域就是名称空间能够作用的范围,按照名字作用范围的不同可以将三个名称空间划分为两个区域:
- 全局作用域:全局存活,全局有效,内置名称空间和全局名称空间就是处于全局范围的。
- 局部作用域:临时存活,局部有效,局部名称空间就是处于局部范围的。
global关键字
那么问题来了,我们该如何在局部内修改全局的名称的值呢?
如果全局名称空间中的名称是可变类型:
l = [1, 2, 3]
def index():
l.append(4)
index()
print(l) # 输出:[1, 2, 3, 4]
如果全局名称空间中的名称是不可变类型:
x = 100
def index():
global x # 使用关键字声明,说明之后的x使用的是全局的x
x = 200
index()
print(x) # 输出:200
"""如果想要在局部名称空间中修改全局名称空间中的名字 那么需要使用关键字global申明"""
nonlocal关键字
问题又来了,知道了怎么在局部名称空间中修改全局名称空间中的名字,那么局部名称空间有多层嵌套该如何修改外层的名字呢?
比如:
def index():
x = 100
def f():
# 如何在f()函数里修改x的值?
f()
print(x)
同样,这个时候也是需要一个关键字,这个关键字就是nonlocal。
def index():
x = 100
def f():
nonlocal x # 使用nonlocal关键字,说明之后的x使用的是外层的x
x = 200
f()
print(x) # 输出:200