python之名称空间与作用域

名称空间

名称空间就是变量名与变量值绑定关系的地方。比如对于x=1,1存放于内存空间,而x与1的对应关系存储在名称空间中。

名称空间分为三类:内置名称空间、全局名称空间、局部名称空间。

image

内置名称空间

内置名称空间存储的是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存入局部名称空间

存活周期:函数被调用时产生,函数调用结束时销毁。

名称的查找顺序

如果要去找一个名称,有这么多个名称空间,我们该去那个名称空间找呢?

在查找名称之前,要先知道直接在哪一个空间内。知道了自己所在的空间后,先在自己空间内查找,找不到在向外寻找,所以查找顺序应该是:局部名称空间 >>> 全局名称空间 >>> 内置名称空间

image

# 案例一
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

image

posted @ 2022-03-17 16:51  Yume_Minami  阅读(77)  评论(0编辑  收藏  举报