名称空间与作用域

一、名称空间的概念

名称空间(namespace)就是用来存储变量名与数据值绑定关系的地方(我们也可以简单的理解为就是存储变量名的地方)

二、分类

在程序执行期间最多会存在三种名称空间

2.1 内建名称空间

伴随python解释器的启动/关闭而产生/回收,因而是第一个被加载的名称空间,用来存放一些内置的名字,eg:
len print input

2.2 全局名称空间

伴随python文件的开始执行/执行完毕而产生/回收,是第二个被加载的名称空间,文件执行过程中产生的名字都会存放于该名称空间中,其中,在py文件中,顶格写的代码都在全局名称空间中, 如下

name = 'kevin'  # 变量名name

if  True:
    a = 1  # 变量名a

while True:
    x = 10  # 变量名x

 def index():  # 函数名index
        pass

2.3 局部名称空间

伴随函数的调用/结束而临时产生/回收,函数的形参、函数内定义的名字都会被存放于该名称空间中

def index(x):
    y=3 #调用函数时,才会执行函数代码,名字x和y都存放于该函数的局部名称空间中

2.4 查看

可以调用内建函数globals()和locals()来分别查看全局名称空间和局部名称空间的名字,返回的结果都是字典格式。使用locals()查看时,要在局部查看。

三、名字的查找顺序

第一步、首先先确定你所在的位置
第二步、如果在局部中:局部 >>> 全局 >>> 内置
第三步、如果在全局中:全局 >>> 内置

# 局部
x=100
def func():
    x=300
    print(x)
func()  # 结果是300


# 全局
x=100
def func():
    x=300
func()  
print(x)  # 结果是100

Python支持函数的嵌套定义,在内嵌的函数内查找名字时,会优先查找自己局部作用域的名字,然后由内而外一层层查找外部嵌套函数定义的作用域,没有找到,则查找全局作用域

"""
函数体代码中名字的查找顺序在函数定义阶段就已经固定死了
"""

# x = 888
def index():
    # x = 666

    def index1():
        # x = 555

        def index2():
            # x = 444

            def index3():
                # x = 333

                def index4():
                    x = 222
                    print(x)
                index4()

            index3()

        index2()

    index1()


index()

四、名称空间的作用域

作用域就是作用的范围

  1. 内置的
    在任何阶段任何时间都可以使用 (全局有效)
  2. 全局的
    在任何阶段任何时间都可以使用 (全局有效)
  3. 局部的
    在函数内部阶段使用 (局部有效)

五、global与nonlocal关键字的使用

5.1 global

局部修改全局的

  1. 修改的是不可变类型,必须使用global关键字声明一下
  2. 修改的是可变类型,就可以直接修改

1.当全局作用域中的值为不可变类型时
在函数内,无论嵌套多少层,都可以查看到全局作用域的名字

# 局部空间中重新赋值也不会改变全局中x的值,x仍然是100
x = 100
def index():
    x = 200
index()
print(x)  # x的结果是100

想要在函数内修改全局名称空间中名字的值,需要用到global关键字

x = 100
def index():
    # 局部修改全局的变量
    global x  # 声明变量x为全局的x
    x = 200
index()
print(x)  # x的结果是200

2.当实参的值为不可变类型时,函数体对该值的修改将会直接反应到原值

x = ['kevin', 'jack']
def index():
    # 局部修改全局的变量
    x.append('tony')
index()
print(x)
# 输出结果是:['kevin', 'jack','tony']

5.2 nonlocal

内部的局部修改外部的局部

  1. 如果是不可变类型,必须使用nonlocal关键字声明一下
  2. 如果是可变类型,就可以直接改变

1.不可变类型

# 对于嵌套多层的函数中,
# 不可变类型时,嵌套内部的赋值改变不了外部的值,x的值是60
def index():
    x = 60
    def func():
        x = 90
    func()
    print(x)
index()  # x的结果是60

# 想要内部的局部修改外部的局部,需要使用nonlocal关键字
def index():
    x = 100
    def func():
        nonlocal x
        x = 200
    func()  # 调用func(),修改index()作用域中名字x的值
    print(x)  # 在index()作用域查看x
index()  # x的结果是90
# nonlocal x会从当前函数的外层函数开始一层层去查找名字x,若是一直到最外层函数都找不到,则会抛出异常。

2.可变类型

# 可变类型
def index():
    x = ['a', 'b']
    def func():
        x.append('c')
    func()
    print(x)  # ['a', 'b', 'c']
index()

posted @ 2023-02-28 19:01  星空看海  阅读(66)  评论(0编辑  收藏  举报